diff --git a/src/gui/applyprogressdialog.cpp b/src/gui/applyprogressdialog.cpp index 4d30dd4..a3f7412 100644 --- a/src/gui/applyprogressdialog.cpp +++ b/src/gui/applyprogressdialog.cpp @@ -1,464 +1,464 @@ /************************************************************************* * Copyright (C) 2008 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/applyprogressdialog.h" #include "gui/applyprogressdialogwidget.h" #include "gui/applyprogressdetailswidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const QString ApplyProgressDialog::m_TimeFormat = QStringLiteral("hh:mm:ss"); static QWidget* mainWindow(QWidget* w) { while (w && w->parentWidget()) w = w->parentWidget(); return w; } /** Creates a new ProgressDialog @param parent pointer to the parent widget @param orunner the OperationRunner whose progress this dialog is showing */ ApplyProgressDialog::ApplyProgressDialog(QWidget* parent, OperationRunner& orunner) : QDialog(parent), m_ProgressDialogWidget(new ApplyProgressDialogWidget(this)), m_ProgressDetailsWidget(new ApplyProgressDetailsWidget(this)), m_OperationRunner(orunner), m_Report(nullptr), m_SavedParentTitle(mainWindow(this)->windowTitle()), m_Timer(this), m_Time(), m_CurrentOpItem(nullptr), m_CurrentJobItem(nullptr), m_LastReportUpdate(0) { QVBoxLayout *mainLayout = new QVBoxLayout(this); setLayout(mainLayout); mainLayout->addWidget(&dialogWidget()); QFrame* detailsBox = new QFrame(this); mainLayout->addWidget(detailsBox); QVBoxLayout *detailsLayout = new QVBoxLayout(detailsBox); detailsLayout->addWidget(&detailsWidget()); detailsWidget().hide(); setAttribute(Qt::WA_ShowModal, true); dialogButtonBox = new QDialogButtonBox; okButton = dialogButtonBox->addButton(QDialogButtonBox::Ok); cancelButton = dialogButtonBox->addButton(QDialogButtonBox::Cancel); detailsButton = new QPushButton; detailsButton->setText(xi18nc("@action:button", "&Details") + QStringLiteral(" >>")); - detailsButton->setIcon(QIcon::fromTheme(QStringLiteral("help-about")).pixmap(IconSize(KIconLoader::Toolbar))); + detailsButton->setIcon(QIcon::fromTheme(QStringLiteral("help-about")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Toolbar))); dialogButtonBox->addButton(detailsButton, QDialogButtonBox::ActionRole); mainLayout->addWidget(dialogButtonBox); dialogWidget().treeTasks().setColumnWidth(0, width() * 8 / 10); - detailsWidget().buttonBrowser().setIcon(QIcon::fromTheme(QStringLiteral("document-open")).pixmap(IconSize(KIconLoader::Toolbar))); - detailsWidget().buttonSave().setIcon(QIcon::fromTheme(QStringLiteral("document-save")).pixmap(IconSize(KIconLoader::Toolbar))); + detailsWidget().buttonBrowser().setIcon(QIcon::fromTheme(QStringLiteral("document-open")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Toolbar))); + detailsWidget().buttonSave().setIcon(QIcon::fromTheme(QStringLiteral("document-save")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Toolbar))); setupConnections(); KConfigGroup kcg(KSharedConfig::openConfig(), "applyProgressDialog"); restoreGeometry(kcg.readEntry("Geometry", QByteArray())); } /** Destroys a ProgressDialog */ ApplyProgressDialog::~ApplyProgressDialog() { KConfigGroup kcg(KSharedConfig::openConfig(), "applyProgressDialog"); kcg.writeEntry("Geometry", saveGeometry()); delete m_Report; } void ApplyProgressDialog::setupConnections() { connect(&operationRunner(), &OperationRunner::progressSub, &dialogWidget().progressSub(), &QProgressBar::setValue); connect(&operationRunner(), &OperationRunner::finished, this, &ApplyProgressDialog::onAllOpsFinished); connect(&operationRunner(), &OperationRunner::cancelled, this, &ApplyProgressDialog::onAllOpsCancelled); connect(&operationRunner(), &OperationRunner::error, this, &ApplyProgressDialog::onAllOpsError); connect(&operationRunner(), &OperationRunner::opStarted, this, &ApplyProgressDialog::onOpStarted); connect(&operationRunner(), &OperationRunner::opFinished, this, &ApplyProgressDialog::onOpFinished); connect(&timer(), &QTimer::timeout, this, &ApplyProgressDialog::onSecondElapsed); connect(&detailsWidget().buttonSave(), &QPushButton::clicked, this, &ApplyProgressDialog::saveReport); connect(&detailsWidget().buttonBrowser(), &QPushButton::clicked, this, &ApplyProgressDialog::browserReport); connect(dialogButtonBox, &QDialogButtonBox::accepted, this, &ApplyProgressDialog::onOkButton); connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &ApplyProgressDialog::onCancelButton); connect(detailsButton, &QPushButton::clicked, this, &ApplyProgressDialog::toggleDetails); } /** Shows the dialog */ void ApplyProgressDialog::show() { setStatus(xi18nc("@info:progress", "Setting up...")); resetReport(); dialogWidget().progressTotal().setRange(0, operationRunner().numJobs()); dialogWidget().progressTotal().setValue(0); dialogWidget().treeTasks().clear(); okButton->setVisible(false); okButton->setEnabled(false); cancelButton->setVisible(true); cancelButton->setEnabled(true); timer().start(1000); time().start(); setLastReportUpdate(0); onSecondElapsed(); // resets the total time output label QDialog::show(); } void ApplyProgressDialog::resetReport() { delete m_Report; m_Report = new Report(nullptr); detailsWidget().editReport().clear(); detailsWidget().editReport().setCursorWidth(0); detailsWidget().buttonSave().setEnabled(false); detailsWidget().buttonBrowser().setEnabled(false); connect(&report(), &Report::outputChanged, this, &ApplyProgressDialog::updateReportUnforced); } void ApplyProgressDialog::closeEvent(QCloseEvent* e) { e->ignore(); operationRunner().isRunning() ? onCancelButton() : onOkButton(); } void ApplyProgressDialog::toggleDetails() { const bool isVisible = detailsWidget().isVisible(); detailsWidget().setVisible(!isVisible); detailsButton->setText(xi18nc("@action:button", "&Details") + (isVisible ? QStringLiteral(" >>") : QStringLiteral(" <<"))); } void ApplyProgressDialog::onDetailsButton() { updateReport(true); return; } void ApplyProgressDialog::onCancelButton() { if (operationRunner().isRunning()) { // only cancel once if (operationRunner().isCancelling()) return; // suspend the runner, so it doesn't happily carry on while the user decides // if he really wants to cancel operationRunner().suspendMutex().lock(); if (KMessageBox::questionYesNo(this, xi18nc("@info", "Do you really want to cancel?"), xi18nc("@title:window", "Cancel Running Operations"), KGuiItem(xi18nc("@action:button", "Yes, Cancel Operations"), QStringLiteral("dialog-ok")), KStandardGuiItem::no()) == KMessageBox::Yes) // in the meantime while we were showing the messagebox, the runner might have finished. if (operationRunner().isRunning()) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); cancelButton->setEnabled(false); setStatus(xi18nc("@info:progress", "Waiting for operation to finish...")); repaint(); dialogWidget().repaint(); QApplication::restoreOverrideCursor(); operationRunner().cancel(); } operationRunner().suspendMutex().unlock(); } return; } void ApplyProgressDialog::onOkButton() { mainWindow(this)->setWindowTitle(savedParentTitle()); QDialog::accept(); } void ApplyProgressDialog::onAllOpsFinished() { allOpsDone(xi18nc("@info:progress", "All operations successfully finished.")); } void ApplyProgressDialog::onAllOpsCancelled() { allOpsDone(xi18nc("@info:progress", "Operations cancelled.")); } void ApplyProgressDialog::onAllOpsError() { allOpsDone(xi18nc("@info:progress", "There were errors while applying operations. Aborted.")); } void ApplyProgressDialog::allOpsDone(const QString& msg) { dialogWidget().progressTotal().setValue(operationRunner().numJobs()); cancelButton->setVisible(false); okButton->setVisible(true); okButton->setEnabled(true); detailsWidget().buttonSave().setEnabled(true); detailsWidget().buttonBrowser().setEnabled(true); timer().stop(); updateReport(true); setStatus(msg); } void ApplyProgressDialog::updateReportUnforced() { updateReport(false); } void ApplyProgressDialog::updateReport(bool force) { // Rendering the HTML in the QTextEdit is extremely expensive. So make sure not to do that // unnecessarily and not too often: // (1) If the widget isn't visible, don't update. // (2) Also don't update if the last update was n msecs ago, BUT // (3) DO update if we're being forced to. if (force || (detailsWidget().isVisible() && time().elapsed() - lastReportUpdate() > 2000)) { detailsWidget().editReport().setHtml(QStringLiteral("") + report().toHtml() + QStringLiteral("")); detailsWidget().editReport().moveCursor(QTextCursor::End); detailsWidget().editReport().ensureCursorVisible(); setLastReportUpdate(time().elapsed()); } } void ApplyProgressDialog::onOpStarted(int num, Operation* op) { addTaskOutput(num, *op); setStatus(op->description()); dialogWidget().progressSub().setValue(0); dialogWidget().progressSub().setRange(0, op->totalProgress()); connect(op, &Operation::jobStarted, this, &ApplyProgressDialog::onJobStarted); connect(op, &Operation::jobFinished, this, &ApplyProgressDialog::onJobFinished); } void ApplyProgressDialog::onJobStarted(Job* job, Operation* op) { for (qint32 i = 0; i < dialogWidget().treeTasks().topLevelItemCount(); i++) { QTreeWidgetItem* item = dialogWidget().treeTasks().topLevelItem(i); if (item == nullptr || reinterpret_cast(item->data(0, Qt::UserRole).toULongLong()) != op) continue; QTreeWidgetItem* child = new QTreeWidgetItem(); child->setText(0, job->description()); - child->setIcon(0, QIcon::fromTheme(job->statusIcon()).pixmap(IconSize(KIconLoader::Small))); + child->setIcon(0, QIcon::fromTheme(job->statusIcon()).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); child->setText(1, QTime(0, 0).toString(timeFormat())); item->addChild(child); dialogWidget().treeTasks().scrollToBottom(); setCurrentJobItem(child); break; } } void ApplyProgressDialog::onJobFinished(Job* job, Operation* op) { if (currentJobItem()) - currentJobItem()->setIcon(0, QIcon::fromTheme(job->statusIcon()).pixmap(IconSize(KIconLoader::Small))); + currentJobItem()->setIcon(0, QIcon::fromTheme(job->statusIcon()).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); setCurrentJobItem(nullptr); const int current = dialogWidget().progressTotal().value(); dialogWidget().progressTotal().setValue(current + 1); setParentTitle(op->description()); updateReport(true); } void ApplyProgressDialog::onOpFinished(int num, Operation* op) { if (currentOpItem()) { currentOpItem()->setText(0, opDesc(num, *op)); - currentOpItem()->setIcon(0, QIcon::fromTheme(op->statusIcon()).pixmap(IconSize(KIconLoader::Small))); + currentOpItem()->setIcon(0, QIcon::fromTheme(op->statusIcon()).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); } setCurrentOpItem(nullptr); setStatus(op->description()); dialogWidget().progressSub().setValue(op->totalProgress()); updateReport(true); } void ApplyProgressDialog::setParentTitle(const QString& s) { const int percent = dialogWidget().progressTotal().value() * 100 / dialogWidget().progressTotal().maximum(); mainWindow(this)->setWindowTitle(QString::number(percent) + QStringLiteral("% - ") + s + QStringLiteral(" - ") + savedParentTitle()); } void ApplyProgressDialog::setStatus(const QString& s) { setWindowTitle(s); dialogWidget().status().setText(s); setParentTitle(s); } QString ApplyProgressDialog::opDesc(int num, const Operation& op) const { return xi18nc("@info:progress", "[%1/%2] - %3: %4", num, operationRunner().numOperations(), op.statusText(), op.description()); } void ApplyProgressDialog::addTaskOutput(int num, const Operation& op) { QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setIcon(0, QIcon::fromTheme(op.statusIcon()).pixmap(IconSize(KIconLoader::Small))); + item->setIcon(0, QIcon::fromTheme(op.statusIcon()).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); item->setText(0, opDesc(num, op)); item->setText(1, QTime(0, 0).toString(timeFormat())); QFont f; f.setWeight(QFont::Bold); item->setFont(0, f); item->setFont(1, f); item->setData(0, Qt::UserRole, reinterpret_cast(&op)); dialogWidget().treeTasks().addTopLevelItem(item); dialogWidget().treeTasks().scrollToBottom(); setCurrentOpItem(item); } void ApplyProgressDialog::onSecondElapsed() { if (currentJobItem()) { QTime t = QTime::fromString(currentJobItem()->text(1), timeFormat()).addSecs(1); currentJobItem()->setText(1, t.toString(timeFormat())); } if (currentOpItem()) { QTime t = QTime::fromString(currentOpItem()->text(1), timeFormat()).addSecs(1); currentOpItem()->setText(1, t.toString(timeFormat()));; } const QTime outputTime = QTime(0, 0).addMSecs(time().elapsed()); dialogWidget().totalTime().setText(xi18nc("@info:progress", "Total Time: %1", outputTime.toString(timeFormat()))); } void ApplyProgressDialog::keyPressEvent(QKeyEvent* e) { e->accept(); switch (e->key()) { case Qt::Key_Return: case Qt::Key_Enter: if (okButton->isEnabled()) onOkButton(); break; case Qt::Key_Escape: cancelButton->isEnabled() ? onCancelButton() : onOkButton(); break; default: break; } } void ApplyProgressDialog::saveReport() { const QUrl url = QFileDialog::getSaveFileUrl(); if (url.isEmpty()) return; QTemporaryFile tempFile; if (tempFile.open()) { QTextStream s(&tempFile); HtmlReport html; s << html.header() << report().toHtml() << html.footer(); tempFile.close(); KIO::CopyJob* job = KIO::move(QUrl::fromLocalFile(tempFile.fileName()), url, KIO::HideProgressInfo); job->exec(); if (job->error()) job->uiDelegate()->showErrorMessage(); } else KMessageBox::sorry(this, xi18nc("@info", "Could not create temporary file when trying to save to %1.", url.fileName()), xi18nc("@title:window", "Could Not Save Report.")); } void ApplyProgressDialog::browserReport() { QTemporaryFile file; // Make sure the temp file is created somewhere another user can read it: KRun::runUrl() will open // the file as the logged in user, not as the user running our application. file.setFileTemplate(QStringLiteral("/tmp/") + QCoreApplication::applicationName() + QStringLiteral("-XXXXXX.html")); file.setAutoRemove(false); if (file.open()) { QTextStream s(&file); HtmlReport html; s << html.header() << report().toHtml() << html.footer(); // set the temp file's permission for everyone to read it. file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadGroup | QFile::ReadOther); if (!KRun::runUrl(QUrl::fromLocalFile(file.fileName()), QStringLiteral("text/html"), this, KRun::RunFlags())) KMessageBox::sorry(this, xi18nc("@info", "The configured external browser could not be run. Please check your settings."), xi18nc("@title:window", "Could Not Launch Browser.")); } else KMessageBox::sorry(this, xi18nc("@info", "Could not create temporary file %1 for writing.", file.fileName()), i18nc("@title:window", "Could Not Launch Browser.")); } diff --git a/src/gui/devicepropsdialog.cpp b/src/gui/devicepropsdialog.cpp index 883d11b..8f42dea 100644 --- a/src/gui/devicepropsdialog.cpp +++ b/src/gui/devicepropsdialog.cpp @@ -1,174 +1,174 @@ /************************************************************************* * Copyright (C) 2008, 2009 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/devicepropsdialog.h" #include "gui/devicepropswidget.h" #include "gui/smartdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /** Creates a new DevicePropsDialog @param parent pointer to the parent widget @param d the Device to show properties for */ DevicePropsDialog::DevicePropsDialog(QWidget* parent, Device& d) : QDialog(parent), m_Device(d), m_DialogWidget(new DevicePropsWidget(this)) { mainLayout = new QVBoxLayout(this); setLayout(mainLayout); mainLayout->addWidget(&dialogWidget()); setWindowTitle(xi18nc("@title:window", "Device Properties: %1", device().deviceNode())); setupDialog(); setupConnections(); KConfigGroup kcg(KSharedConfig::openConfig(), "devicePropsDialog"); restoreGeometry(kcg.readEntry("Geometry", QByteArray())); } /** Destroys a DevicePropsDialog */ DevicePropsDialog::~DevicePropsDialog() { KConfigGroup kcg(KSharedConfig::openConfig(), "devicePropsDialog"); kcg.writeEntry("Geometry", saveGeometry()); } void DevicePropsDialog::setupDialog() { dialogButtonBox = new QDialogButtonBox; okButton = dialogButtonBox->addButton(QDialogButtonBox::Ok); cancelButton = dialogButtonBox->addButton(QDialogButtonBox::Cancel); mainLayout->addWidget(dialogButtonBox); okButton->setEnabled(false); cancelButton->setFocus(); cancelButton->setDefault(true); connect(dialogButtonBox, &QDialogButtonBox::accepted, this, &DevicePropsDialog::accept); connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &DevicePropsDialog::reject); QString type = QStringLiteral("---"); QString maxPrimaries = QStringLiteral("---"); if (device().partitionTable() != nullptr) { type = (device().partitionTable()->isReadOnly()) ? xi18nc("@label device", "%1 (read only)", device().partitionTable()->typeName()) : device().partitionTable()->typeName(); maxPrimaries = QStringLiteral("%1/%2").arg(device().partitionTable()->numPrimaries()).arg(device().partitionTable()->maxPrimaries()); dialogWidget().partTableWidget().setReadOnly(true); dialogWidget().partTableWidget().setPartitionTable(device().partitionTable()); if (device().partitionTable()->type() == PartitionTable::msdos) dialogWidget().radioCylinderBased().setChecked(true); else if (device().partitionTable()->type() == PartitionTable::msdos_sectorbased) dialogWidget().radioSectorBased().setChecked(true); else dialogWidget().hideTypeRadioButtons(); } else { dialogWidget().partTableWidget().setVisible(false); dialogWidget().hideTypeRadioButtons(); } dialogWidget().type().setText(type); dialogWidget().capacity().setText(Capacity::formatByteSize(device().capacity())); dialogWidget().totalSectors().setText(QLocale().toString(device().totalLogical())); if (device().type() == Device::Type::Disk_Device) { const DiskDevice& disk = dynamic_cast(device()); dialogWidget().primariesMax().setText(maxPrimaries); dialogWidget().logicalSectorSize().setText(Capacity::formatByteSize(disk.logicalSectorSize())); dialogWidget().physicalSectorSize().setText(Capacity::formatByteSize(disk.physicalSectorSize())); if (device().smartStatus().isValid()) { if (device().smartStatus().status()) { dialogWidget().smartStatusText().setText(xi18nc("@label SMART disk status", "good")); - dialogWidget().smartStatusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(IconSize(KIconLoader::Small))); + dialogWidget().smartStatusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); } else { dialogWidget().smartStatusText().setText(xi18nc("@label SMART disk status", "BAD")); - dialogWidget().smartStatusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-warning")).pixmap(IconSize(KIconLoader::Small))); + dialogWidget().smartStatusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-warning")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); } } else { dialogWidget().smartStatusText().setText(xi18nc("@label", "(unknown)")); dialogWidget().smartStatusIcon().setVisible(false); dialogWidget().buttonSmartMore().setVisible(false); } } else { if (device().type() == Device::Type::LVM_Device) dialogWidget().type().setText(xi18nc("@label device", "LVM Volume Group")); else if (device().type() == Device::Type::SoftwareRAID_Device) dialogWidget().type().setText(xi18nc("@label device", "Software RAID Device")); else dialogWidget().type().setText(xi18nc("@label device", "Volume Manager Device")); //TODO: add Volume Manger Device info dialogWidget().smartStatusText().setVisible(false); dialogWidget().smartStatusIcon().setVisible(false); dialogWidget().buttonSmartMore().setVisible(false); } setMinimumSize(dialogWidget().size()); resize(dialogWidget().size()); } void DevicePropsDialog::setupConnections() { connect(&dialogWidget().radioSectorBased(), &QRadioButton::toggled, this, &DevicePropsDialog::setDirty); connect(&dialogWidget().radioCylinderBased(), &QRadioButton::toggled, this, &DevicePropsDialog::setDirty); connect(&dialogWidget().buttonSmartMore(), &QPushButton::clicked, this, &DevicePropsDialog::onButtonSmartMore); } void DevicePropsDialog::setDirty(bool) { okButton->setEnabled(true); okButton->setDefault(true); } bool DevicePropsDialog::cylinderBasedAlignment() const { return dialogWidget().radioCylinderBased().isChecked(); } bool DevicePropsDialog::sectorBasedAlignment() const { return dialogWidget().radioSectorBased().isChecked(); } void DevicePropsDialog::onButtonSmartMore(bool) { QPointer dlg = new SmartDialog(this, device()); dlg->exec(); delete dlg; } diff --git a/src/gui/filesystemsupportdialog.cpp b/src/gui/filesystemsupportdialog.cpp index 487b534..eeabe1e 100644 --- a/src/gui/filesystemsupportdialog.cpp +++ b/src/gui/filesystemsupportdialog.cpp @@ -1,120 +1,120 @@ /************************************************************************* * Copyright (C) 2008, 2010 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/filesystemsupportdialog.h" #include "gui/filesystemsupportdialogwidget.h" #include #include #include #include #include #include #include #include /** Creates a new FileSystemSupportDialog @param parent the parent object */ FileSystemSupportDialog::FileSystemSupportDialog(QWidget* parent) : QDialog(parent), m_FileSystemSupportDialogWidget(new FileSystemSupportDialogWidget(this)) { QVBoxLayout *mainLayout = new QVBoxLayout(this); setLayout(mainLayout); mainLayout->addWidget(&dialogWidget()); setWindowTitle(xi18nc("@title:window", "File System Support")); dialogButtonBox = new QDialogButtonBox(this); dialogButtonBox -> setStandardButtons(QDialogButtonBox::Ok); mainLayout->addWidget(dialogButtonBox); setupDialog(); setupConnections(); KConfigGroup kcg(KSharedConfig::openConfig(), "fileSystemSupportDialog"); restoreGeometry(kcg.readEntry("Geometry", QByteArray())); } /** Destroys a FileSystemSupportDialog */ FileSystemSupportDialog::~FileSystemSupportDialog() { KConfigGroup kcg(KSharedConfig::openConfig(), "fileSystemSupportDialog"); kcg.writeEntry("Geometry", saveGeometry()); } QSize FileSystemSupportDialog::sizeHint() const { return QSize(690, 490); } void FileSystemSupportDialog::setupDialog() { - QIcon yes = QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(IconSize(KIconLoader::Toolbar)); - QIcon no = QIcon::fromTheme(QStringLiteral("dialog-error")).pixmap(IconSize(KIconLoader::Toolbar)); + QIcon yes = QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Toolbar)); + QIcon no = QIcon::fromTheme(QStringLiteral("dialog-error")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Toolbar)); dialogWidget().tree().clear(); for (const auto &fs : FileSystemFactory::map()) { if (fs->type() == FileSystem::Type::Unknown || fs->type() == FileSystem::Type::Extended || fs->type() == FileSystem::Type::Luks || fs->type() == FileSystem::Type::Luks2) { continue; } QTreeWidgetItem* item = new QTreeWidgetItem(); int i = 0; item->setText(i++, fs->name()); item->setIcon(i++, fs->supportCreate() ? yes : no); item->setIcon(i++, fs->supportGrow() ? yes : no); item->setIcon(i++, fs->supportShrink() ? yes : no); item->setIcon(i++, fs->supportMove() ? yes : no); item->setIcon(i++, fs->supportCopy() ? yes : no); item->setIcon(i++, fs->supportCheck() ? yes : no); item->setIcon(i++, fs->supportGetLabel() ? yes : no); item->setIcon(i++, fs->supportSetLabel() ? yes : no); item->setIcon(i++, fs->supportGetUsed() ? yes : no); item->setIcon(i++, fs->supportBackup() ? yes : no); // there is no FileSystem::supportRestore(), because we currently can't tell // if a file is an image of a supported or unsupported (or even invalid) filesystem item->setIcon(i++, yes); item->setText(i++, fs->supportToolName().name.isEmpty() ? QStringLiteral("---") : fs->supportToolName().name); dialogWidget().tree().addTopLevelItem(item); } for (int i = 0; i < dialogWidget().tree().columnCount(); i++) dialogWidget().tree().resizeColumnToContents(i); dialogWidget().tree().sortItems(0, Qt::AscendingOrder); } void FileSystemSupportDialog::setupConnections() { connect(dialogButtonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FileSystemSupportDialog::close); connect(&dialogWidget().buttonRescan(), &QPushButton::clicked, this, &FileSystemSupportDialog::onButtonRescanClicked); } void FileSystemSupportDialog::onButtonRescanClicked() { FileSystemFactory::init(); setupDialog(); } diff --git a/src/gui/listdevices.cpp b/src/gui/listdevices.cpp index c068f0d..a2ed8c4 100644 --- a/src/gui/listdevices.cpp +++ b/src/gui/listdevices.cpp @@ -1,88 +1,88 @@ /************************************************************************* * Copyright (C) 2008-2010 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/listdevices.h" #include #include #include #include class ListDeviceWidgetItem : public QListWidgetItem { public: ListDeviceWidgetItem(const Device& d) : - QListWidgetItem(QIcon::fromTheme(d.iconName()).pixmap(IconSize(KIconLoader::Desktop)), d.prettyName()), + QListWidgetItem(QIcon::fromTheme(d.iconName()).pixmap(KIconLoader::global()->currentSize(KIconLoader::Desktop)), d.prettyName()), deviceNode(d.deviceNode()) { setToolTip(d.prettyName()); setSizeHint(QSize(0, 32)); } const QString deviceNode; }; /** Creates a new ListDevices instance. @param parent the parent widget */ ListDevices::ListDevices(QWidget* parent) : QWidget(parent), Ui::ListDevicesBase(), m_ActionCollection(nullptr) { setupUi(this); } void ListDevices::updateDevices(const OperationStack::Devices& devices) { listDevices().clear(); for (const auto &d : devices) listDevices().addItem(new ListDeviceWidgetItem(*d)); } void ListDevices::on_m_ListDevices_itemSelectionChanged() { if (listDevices().selectedItems().size() == 1) { ListDeviceWidgetItem* item = dynamic_cast(listDevices().selectedItems()[0]); if (item != nullptr) emit selectionChanged(item->deviceNode); } } void ListDevices::on_m_ListDevices_itemDoubleClicked(QListWidgetItem* list_item) { ListDeviceWidgetItem* item = dynamic_cast(list_item); if (item != nullptr) emit deviceDoubleClicked(item->deviceNode); } bool ListDevices::setSelectedDevice(const QString& device_node) { QList items = listDevices().findItems(device_node, Qt::MatchContains); if (items.size() > 0) { listDevices().setCurrentItem(items[0]); return true; } return false; } diff --git a/src/gui/listoperations.cpp b/src/gui/listoperations.cpp index 77362ed..bea6dca 100644 --- a/src/gui/listoperations.cpp +++ b/src/gui/listoperations.cpp @@ -1,50 +1,50 @@ /************************************************************************* * Copyright (C) 2008, 2009 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/listoperations.h" #include #include #include #include /** Creates a new ListOperations instance. @param parent the parent widget */ ListOperations::ListOperations(QWidget* parent) : QWidget(parent), Ui::ListOperationsBase(), m_ActionCollection(nullptr) { setupUi(this); } void ListOperations::updateOperations(const OperationStack::Operations& ops) { listOperations().clear(); for (const auto &op : ops) { - QListWidgetItem* item = new QListWidgetItem(QIcon::fromTheme(op->iconName()).pixmap(IconSize(KIconLoader::Small)), op->description()); + QListWidgetItem* item = new QListWidgetItem(QIcon::fromTheme(op->iconName()).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small)), op->description()); item->setToolTip(op->description()); listOperations().addItem(item); } listOperations().scrollToBottom(); } diff --git a/src/gui/partitionmanagerwidget.cpp b/src/gui/partitionmanagerwidget.cpp index 7c6252e..dbf0135 100644 --- a/src/gui/partitionmanagerwidget.cpp +++ b/src/gui/partitionmanagerwidget.cpp @@ -1,800 +1,800 @@ /************************************************************************* * Copyright (C) 2008-2010 by Volker Lanz * * Copyright (C) 2015 by Teo Mrnjavac * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/partitionmanagerwidget.h" #include "gui/partpropsdialog.h" #include "gui/resizedialog.h" #include "gui/newdialog.h" #include "gui/applyprogressdialog.h" #include "gui/insertdialog.h" #include "gui/editmountpointdialog.h" #include "util/guihelpers.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class PartitionTreeWidgetItem : public QTreeWidgetItem { Q_DISABLE_COPY(PartitionTreeWidgetItem) public: PartitionTreeWidgetItem(const Partition* p) : QTreeWidgetItem(), m_Partition(p) {} const Partition* partition() const { return m_Partition; } private: const Partition* m_Partition; }; /** Creates a new PartitionManagerWidget instance. @param parent the parent widget */ PartitionManagerWidget::PartitionManagerWidget(QWidget* parent) : QWidget(parent), Ui::PartitionManagerWidgetBase(), m_OperationStack(nullptr), m_SelectedDevice(nullptr), m_ClipboardPartition(nullptr) { setupUi(this); treePartitions().header()->setStretchLastSection(false); treePartitions().header()->setContextMenuPolicy(Qt::CustomContextMenu); } PartitionManagerWidget::~PartitionManagerWidget() { saveConfig(); } void PartitionManagerWidget::init(OperationStack* ostack) { m_OperationStack = ostack; // TODO: shouldn't this also go to the main window class? FileSystemFactory::init(); loadConfig(); setupConnections(); } void PartitionManagerWidget::loadConfig() { QList colWidths = Config::treePartitionColumnWidths(); QList colPositions = Config::treePartitionColumnPositions(); QList colVisible = Config::treePartitionColumnVisible(); QHeaderView* header = treePartitions().header(); for (int i = 0; i < treePartitions().columnCount(); i++) { if (colPositions[0] != -1 && colPositions.size() > i) header->moveSection(header->visualIndex(i), colPositions[i]); if (colVisible[0] != -1 && colVisible.size() > i) treePartitions().setColumnHidden(i, colVisible[i] == 0); if (colWidths[0] != -1 && colWidths.size() > i) treePartitions().setColumnWidth(i, colWidths[i]); } } void PartitionManagerWidget::saveConfig() const { QList colWidths; QList colPositions; QList colVisible; for (int i = 0; i < treePartitions().columnCount(); i++) { colPositions.append(treePartitions().header()->visualIndex(i)); colVisible.append(treePartitions().isColumnHidden(i) ? 0 : 1); colWidths.append(treePartitions().columnWidth(i)); } Config::setTreePartitionColumnPositions(colPositions); Config::setTreePartitionColumnVisible(colVisible); Config::setTreePartitionColumnWidths(colWidths); Config::self()->save(); } void PartitionManagerWidget::setupConnections() { connect(treePartitions().header(), &QHeaderView::customContextMenuRequested, this, &PartitionManagerWidget::onHeaderContextMenu); } void PartitionManagerWidget::clear() { setSelectedDevice(nullptr); setClipboardPartition(nullptr); treePartitions().clear(); partTableWidget().clear(); } void PartitionManagerWidget::setSelectedPartition(const Partition* p) { if (p == nullptr) { treePartitions().setCurrentItem(nullptr); emit selectedPartitionChanged(nullptr); updatePartitions(); } else partTableWidget().setActivePartition(p); } Partition* PartitionManagerWidget::selectedPartition() { if (selectedDevice() == nullptr || selectedDevice()->partitionTable() == nullptr || partTableWidget().activeWidget() == nullptr) return nullptr; return partTableWidget().activeWidget()->partition(); } void PartitionManagerWidget::setSelectedDevice(const QString& deviceNode) { QReadLocker lockDevices(&operationStack().lock()); const auto previewDevices = operationStack().previewDevices(); for (const auto &d : previewDevices) { if (d->deviceNode() == deviceNode) { setSelectedDevice(d); return; } } setSelectedDevice(nullptr); } void PartitionManagerWidget::setSelectedDevice(Device* d) { m_SelectedDevice = d; setSelectedPartition(nullptr); } static QTreeWidgetItem* createTreeWidgetItem(const Partition& p) { QTreeWidgetItem* item = new PartitionTreeWidgetItem(&p); int i = 0; item->setText(i++, p.deviceNode()); if (p.roles().has(PartitionRole::Luks) && (p.fileSystem().name() != p.fileSystem().nameForType(FileSystem::Type::Luks) && p.fileSystem().name() != p.fileSystem().nameForType(FileSystem::Type::Luks2))) item->setText(i, xi18nc("@item:intable Encrypted file systems, e.g. btrfs[Encrypted]", "%1 [Encrypted]", p.fileSystem().name())); else item->setText(i, p.fileSystem().name()); item->setIcon(i, createFileSystemColor(p.fileSystem().type(), 14)); i++; item->setText(i, p.mountPoint()); if (p.isMounted()) - item->setIcon(i, QIcon::fromTheme(QStringLiteral("object-locked")).pixmap(IconSize(KIconLoader::Panel))); + item->setIcon(i, QIcon::fromTheme(QStringLiteral("object-locked")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Panel))); i++; item->setText(i++, p.fileSystem().label()); item->setText(i++, p.fileSystem().uuid()); item->setText(i++, p.label()); item->setText(i++, p.uuid()); item->setText(i++, Capacity::formatByteSize(p.capacity())); item->setText(i++, Capacity::formatByteSize(p.used())); item->setText(i++, Capacity::formatByteSize(p.available())); item->setText(i++, QLocale().toString(p.firstSector())); item->setText(i++, QLocale().toString(p.lastSector())); item->setText(i++, QLocale().toString(p.length())); item->setText(i++, PartitionTable::flagNames(p.activeFlags()).join(QStringLiteral(", "))); item->setSizeHint(0, QSize(0, 32)); return item; } void PartitionManagerWidget::updatePartitions() { if (selectedDevice() == nullptr) return; treePartitions().clear(); partTableWidget().clear(); partTableWidget().setPartitionTable(selectedDevice()->partitionTable()); QTreeWidgetItem* deviceItem = new QTreeWidgetItem(); QFont font; font.setBold(true); font.setWeight(75); deviceItem->setFont(0, font); deviceItem->setText(0, selectedDevice()->prettyName()); - deviceItem->setIcon(0, QIcon::fromTheme(selectedDevice()->iconName()).pixmap(IconSize(KIconLoader::Desktop))); + deviceItem->setIcon(0, QIcon::fromTheme(selectedDevice()->iconName()).pixmap(KIconLoader::global()->currentSize(KIconLoader::Desktop))); deviceItem->setSizeHint(0, QSize(0, 32)); treePartitions().addTopLevelItem(deviceItem); if (selectedDevice()->partitionTable() != nullptr) { const auto children = selectedDevice()->partitionTable()->children(); for (const auto * p : children) { QTreeWidgetItem* item = createTreeWidgetItem(*p); for (const auto &child : p->children()) { QTreeWidgetItem* childItem = createTreeWidgetItem(*child); item->addChild(childItem); } deviceItem->addChild(item); item->setExpanded(true); } } deviceItem->setFirstColumnSpanned(true); deviceItem->setExpanded(true); deviceItem->setFlags(Qt::ItemIsEnabled); partTableWidget().update(); } void PartitionManagerWidget::on_m_TreePartitions_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem*) { if (current) { const PartitionTreeWidgetItem* ptwItem = dynamic_cast(current); partTableWidget().setActivePartition(ptwItem ? ptwItem->partition() : nullptr); } else partTableWidget().setActiveWidget(nullptr); } void PartitionManagerWidget::on_m_TreePartitions_itemDoubleClicked(QTreeWidgetItem* item, int) { if (item == treePartitions().topLevelItem(0)) { if (selectedDevice() != nullptr) emit deviceDoubleClicked(selectedDevice()); } else { if (selectedPartition() != nullptr) emit partitionDoubleClicked(selectedPartition()); } } void PartitionManagerWidget::onHeaderContextMenu(const QPoint& p) { showColumnsContextMenu(p, treePartitions()); } void PartitionManagerWidget::on_m_PartTableWidget_itemSelectionChanged(PartWidget* item) { if (item == nullptr) { treePartitions().setCurrentItem(nullptr); emit selectedPartitionChanged(nullptr); return; } const Partition* p = item->partition(); Q_ASSERT(p); if (p) { QList findResult = treePartitions().findItems(p->deviceNode(), Qt::MatchFixedString | Qt::MatchRecursive, 0); for (const auto &treeWidgetItem : findResult) { const PartitionTreeWidgetItem* ptwItem = dynamic_cast(treeWidgetItem); if (ptwItem && ptwItem->partition() == p) { treePartitions().setCurrentItem(treeWidgetItem); break; } } } emit selectedPartitionChanged(p); } void PartitionManagerWidget::on_m_PartTableWidget_customContextMenuRequested(const QPoint& pos) { emit contextMenuRequested(partTableWidget().mapToGlobal(pos)); } void PartitionManagerWidget::on_m_PartTableWidget_itemDoubleClicked() { if (selectedPartition()) emit partitionDoubleClicked(selectedPartition()); } void PartitionManagerWidget::on_m_TreePartitions_customContextMenuRequested(const QPoint& pos) { emit contextMenuRequested(treePartitions().viewport()->mapToGlobal(pos)); } void PartitionManagerWidget::onPropertiesPartition() { if (selectedPartition()) { Partition& p = *selectedPartition(); Q_ASSERT(selectedDevice()); QPointer dlg = new PartPropsDialog(this, *selectedDevice(), p); if (dlg->exec() == QDialog::Accepted) { if (dlg->newFileSystemType() != p.fileSystem().type() || dlg->forceRecreate()) operationStack().push(new CreateFileSystemOperation(*selectedDevice(), p, dlg->newFileSystemType())); if (dlg->newLabel() != p.fileSystem().label()) operationStack().push(new SetFileSystemLabelOperation(p, dlg->newLabel())); if (dlg->newFlags() != p.activeFlags()) operationStack().push(new SetPartFlagsOperation(*selectedDevice(), p, dlg->newFlags())); } delete dlg; } } void PartitionManagerWidget::onMountPartition() { Partition* p = selectedPartition(); Q_ASSERT(p); if (p == nullptr) { qWarning() << "no partition selected"; return; } Report report(nullptr); if (p->canMount()) { if (!p->mount(report)) KMessageBox::detailedSorry(this, xi18nc("@info", "The file system on partition %1 could not be mounted.", p->deviceNode()), QStringLiteral("
%1
").arg(report.toText()), xi18nc("@title:window", "Could Not Mount File System.")); } else if (p->canUnmount()) { if (!p->unmount(report)) KMessageBox::detailedSorry(this, xi18nc("@info", "The file system on partition %1 could not be unmounted.", p->deviceNode()), QStringLiteral("
%1
").arg(report.toText()), xi18nc("@title:window", "Could Not Unmount File System.")); } if (p->roles().has(PartitionRole::Logical)) { Partition* parent = dynamic_cast(p->parent()); Q_ASSERT(parent); if (parent != nullptr) parent->checkChildrenMounted(); else qWarning() << "parent is null"; } updatePartitions(); } void PartitionManagerWidget::onDecryptPartition() { Partition* p = selectedPartition(); Q_ASSERT(p); if (p == nullptr) { qWarning() << "no partition selected"; return; } if (!p->roles().has(PartitionRole::Luks)) return; const FileSystem& fsRef = p->fileSystem(); FS::luks* luksFs = const_cast(dynamic_cast(&fsRef)); if (!luksFs) return; if (luksFs->canCryptOpen(p->partitionPath())) { if (!luksFs->cryptOpen(this, p->partitionPath())) KMessageBox::detailedSorry(this, xi18nc("@info", "The encrypted file system on partition " "%1 could not be " "unlocked.", p->deviceNode()), QString(), xi18nc("@title:window", "Could Not Unlock Encrypted File System.")); } else if (luksFs->canCryptClose(p->partitionPath())) { if (!luksFs->cryptClose(p->partitionPath())) KMessageBox::detailedSorry(this, xi18nc("@info", "The encrypted file system on partition " "%1 could not be " "locked.", p->deviceNode()), QString(), xi18nc("@title:window", "Could Not Lock Encrypted File System.")); } updatePartitions(); } void PartitionManagerWidget::onEditMountPoint() { Partition* p = selectedPartition(); Q_ASSERT(p); if (p == nullptr) return; QPointer dlg = new EditMountPointDialog(this, *p); if (dlg->exec() == QDialog::Accepted) updatePartitions(); delete dlg; } static bool checkTooManyPartitions(QWidget* parent, const Device& d, const Partition& p) { Q_ASSERT(d.partitionTable()); if (p.roles().has(PartitionRole::Unallocated) && d.partitionTable()->numPrimaries() >= d.partitionTable()->maxPrimaries() && !p.roles().has(PartitionRole::Logical)) { KMessageBox::sorry(parent, xi18ncp("@info", "There is already one primary partition on this device. This is the maximum number its partition table type can handle." "You cannot create, paste or restore a primary partition on it before you delete an existing one.", "There are already %1 primary partitions on this device. This is the maximum number its partition table type can handle." "You cannot create, paste or restore a primary partition on it before you delete an existing one.", d.partitionTable()->numPrimaries()), xi18nc("@title:window", "Too Many Primary Partitions.")); return true; } return false; } void PartitionManagerWidget::onNewPartition() { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return; } Q_ASSERT(selectedDevice()->partitionTable()); if (selectedDevice()->partitionTable() == nullptr) { qWarning() << "partition table on selected device is null"; return; } if (checkTooManyPartitions(this, *selectedDevice(), *selectedPartition())) return; Partition* newPartition = NewOperation::createNew(*selectedPartition(), static_cast(Config::defaultFileSystem())); QPointer dlg = new NewDialog(this, *selectedDevice(), *newPartition, selectedDevice()->partitionTable()->childRoles(*selectedPartition())); if (dlg->exec() == QDialog::Accepted) operationStack().push(new NewOperation(*selectedDevice(), newPartition)); else delete newPartition; delete dlg; } void PartitionManagerWidget::onDeletePartition(bool shred) { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return; } if (selectedPartition()->roles().has(PartitionRole::Logical)) { Q_ASSERT(selectedPartition()->parent()); if (selectedPartition()->parent() == nullptr) { qWarning() << "parent of selected partition is null."; return; } if (selectedPartition()->number() > 0 && selectedPartition()->parent()->highestMountedChild() > selectedPartition()->number()) { KMessageBox::sorry(this, xi18nc("@info", "The partition %1 cannot currently be deleted because one or more partitions with higher logical numbers are still mounted." "Please unmount all partitions with higher logical numbers than %2 first.", selectedPartition()->deviceNode(), selectedPartition()->number()), xi18nc("@title:window", "Cannot Delete Partition.")); return; } } if (clipboardPartition() == selectedPartition()) { if (KMessageBox::warningContinueCancel(this, xi18nc("@info", "Do you really want to delete the partition that is currently in the clipboard? " "It will no longer be available for pasting after it has been deleted."), xi18nc("@title:window", "Really Delete Partition in the Clipboard?"), KGuiItem(xi18nc("@action:button", "Delete It"), QStringLiteral("arrow-right")), KStandardGuiItem::cancel(), QStringLiteral("reallyDeleteClipboardPartition")) == KMessageBox::Cancel) return; setClipboardPartition(nullptr); } if (shred && Config::shredSource() == Config::EnumShredSource::random) operationStack().push(new DeleteOperation(*selectedDevice(), selectedPartition(), DeleteOperation::ShredAction::RandomShred)); else if (shred && Config::shredSource() == Config::EnumShredSource::zeros) operationStack().push(new DeleteOperation(*selectedDevice(), selectedPartition(), DeleteOperation::ShredAction::ZeroShred)); else operationStack().push(new DeleteOperation(*selectedDevice(), selectedPartition(), DeleteOperation::ShredAction::NoShred)); } void PartitionManagerWidget::onShredPartition() { onDeletePartition(true); } void PartitionManagerWidget::onResizePartition() { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return; } Q_ASSERT(selectedDevice()->partitionTable()); if (selectedDevice()->partitionTable() == nullptr) { qWarning() << "partition table on selected device is null"; return; } // we cannot work with selectedPartition() here because opening and closing the dialog will // clear the selection, so we'll lose the partition after the dialog's been exec'd Partition& p = *selectedPartition(); qint64 freeBefore = selectedDevice()->partitionTable()->freeSectorsBefore(p); qint64 freeAfter = selectedDevice()->partitionTable()->freeSectorsAfter(p); if (selectedDevice()->type() == Device::Type::LVM_Device) { freeBefore = 0; freeAfter = selectedDevice()->partitionTable()->freeSectors(); } QPointer dlg = new ResizeDialog(this, *selectedDevice(), p, p.firstSector() - freeBefore, p.lastSector() + freeAfter); if (dlg->exec() == QDialog::Accepted) { if (dlg->resizedFirstSector() == p.firstSector() && dlg->resizedLastSector() == p.lastSector()) Log(Log::Level::information) << xi18nc("@info:status", "Partition %1 has the same position and size after resize/move. Ignoring operation.", p.deviceNode()); else operationStack().push(new ResizeOperation(*selectedDevice(), p, dlg->resizedFirstSector(), dlg->resizedLastSector())); } if (p.roles().has(PartitionRole::Extended)) { // Even if the user dismissed the resize dialog we must update the partitions // if it's an extended partition: // The dialog has to remove and create unallocated children if the user resizes // an extended partition. We can't know if that has happened, so to avoid // any problems (like, the user resized an extended and then canceled, which would // lead to the unallocated children having the wrong size) do this now. updatePartitions(); } delete dlg; } void PartitionManagerWidget::onCopyPartition() { Q_ASSERT(selectedPartition()); if (selectedPartition() == nullptr) { qWarning() << "selected partition: " << selectedPartition(); return; } setClipboardPartition(selectedPartition()); Log() << xi18nc("@info:status", "Partition %1 has been copied to the clipboard.", selectedPartition()->deviceNode()); } void PartitionManagerWidget::onPastePartition() { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return; } if (clipboardPartition() == nullptr) { qWarning() << "no partition in the clipboard."; return; } if (checkTooManyPartitions(this, *selectedDevice(), *selectedPartition())) return; Device* dSource = operationStack().findDeviceForPartition(clipboardPartition()); Q_ASSERT(dSource); if (dSource == nullptr) { qWarning() << "source partition is null."; return; } Partition* copiedPartition = CopyOperation::createCopy(*selectedPartition(), *clipboardPartition()); if (showInsertDialog(*copiedPartition, clipboardPartition()->length())) operationStack().push(new CopyOperation(*selectedDevice(), copiedPartition, *dSource, clipboardPartition())); else delete copiedPartition; } bool PartitionManagerWidget::showInsertDialog(Partition& insertedPartition, qint64 sourceLength) { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return false; } const bool overwrite = !selectedPartition()->roles().has(PartitionRole::Unallocated); // Make sure the inserted partition has the right parent and logical or primary set. Only then // can PartitionTable::alignPartition() work correctly. selectedPartition()->parent()->reparent(insertedPartition); if (!overwrite) { QPointer dlg = new InsertDialog(this, *selectedDevice(), insertedPartition, *selectedPartition()); int result = dlg->exec(); delete dlg; if (result != QDialog::Accepted) return false; } else if (KMessageBox::warningContinueCancel(this, xi18nc("@info", "You are about to lose all data on partition " "%1." "Overwriting one partition with another (or with an image file) will " "destroy all data on this target partition." "If you continue now and apply the resulting operation in the main " "window, all data currently stored on %1 will " "unrecoverably be overwritten.", selectedPartition()->deviceNode()), xi18nc("@title:window", "Really Overwrite Existing Partition?"), KGuiItem(xi18nc("@action:button", "Overwrite Partition"), QStringLiteral("arrow-right")), KStandardGuiItem::cancel(), QStringLiteral("reallyOverwriteExistingPartition")) == KMessageBox::Cancel) return false; if (insertedPartition.length() < sourceLength) { if (overwrite) KMessageBox::error(this, xi18nc("@info", "The selected partition is not large enough to hold the source partition or the backup file." "Pick another target or resize this partition so it is as large as the source."), xi18nc("@title:window", "Target Not Large Enough")); else KMessageBox::sorry(this, xi18nc("@info", "It is not possible to create the target partition large enough to hold the source." "This may happen if not all partitions on a device are correctly aligned " "or when copying a primary partition into an extended partition."), xi18nc("@title:window", "Cannot Create Target Partition.")); return false; } return true; } void PartitionManagerWidget::onCheckPartition() { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return; } operationStack().push(new CheckOperation(*selectedDevice(), *selectedPartition())); } void PartitionManagerWidget::onBackupPartition() { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return; } QString fileName = QFileDialog::getSaveFileName(this); if (fileName.isEmpty()) return; operationStack().push(new BackupOperation(*selectedDevice(), *selectedPartition(), fileName)); } void PartitionManagerWidget::onRestorePartition() { Q_ASSERT(selectedDevice()); Q_ASSERT(selectedPartition()); if (selectedDevice() == nullptr || selectedPartition() == nullptr) { qWarning() << "selected device: " << selectedDevice() << ", selected partition: " << selectedPartition(); return; } if (checkTooManyPartitions(this, *selectedDevice(), *selectedPartition())) return; QString fileName = QFileDialog::getOpenFileName(this); // QString fileName = "/tmp/backuptest.img"; if (!fileName.isEmpty() && QFile::exists(fileName)) { Partition* restorePartition = RestoreOperation::createRestorePartition(*selectedDevice(), *selectedPartition()->parent(), selectedPartition()->firstSector(), fileName); if (restorePartition->length() > selectedPartition()->length()) { KMessageBox::error(this, xi18nc("@info", "The file system in the image file %1 is too large to be restored to the selected partition.", fileName), xi18nc("@title:window", "Not Enough Space to Restore File System.")); delete restorePartition; return; } if (showInsertDialog(*restorePartition, restorePartition->length())) operationStack().push(new RestoreOperation(*selectedDevice(), restorePartition, fileName)); else delete restorePartition; } } diff --git a/src/gui/smartdialog.cpp b/src/gui/smartdialog.cpp index 78c6c64..d4a48e0 100644 --- a/src/gui/smartdialog.cpp +++ b/src/gui/smartdialog.cpp @@ -1,238 +1,238 @@ /************************************************************************* * Copyright (C) 2010 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/smartdialog.h" #include "gui/smartdialogwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** Creates a new SmartDialog @param parent pointer to the parent widget @param d the Device */ SmartDialog::SmartDialog(QWidget* parent, Device& d) : QDialog(parent), m_Device(d), m_DialogWidget(new SmartDialogWidget(this)) { QVBoxLayout *mainLayout = new QVBoxLayout(this); setLayout(mainLayout); mainLayout->addWidget(&dialogWidget()); setWindowTitle(xi18nc("@title:window", "SMART Properties: %1", device().deviceNode())); buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Close); buttonBox->button(QDialogButtonBox::Save)->setText(xi18nc("@action:button", "Save SMART Report")); buttonBox->button(QDialogButtonBox::Save)->setIcon(QIcon::fromTheme(QStringLiteral("document-save"))); mainLayout->addWidget(buttonBox); setupDialog(); setupConnections(); KConfigGroup kcg(KSharedConfig::openConfig(), "smartDialog"); restoreGeometry(kcg.readEntry("Geometry", QByteArray())); } /** Destroys a SmartDialog */ SmartDialog::~SmartDialog() { KConfigGroup kcg(KSharedConfig::openConfig(), "smartDialog"); kcg.writeEntry("Geometry", saveGeometry()); } void SmartDialog::setupDialog() { if (device().smartStatus().isValid()) { if (device().smartStatus().status()) { dialogWidget().statusText().setText(xi18nc("@label SMART disk status", "good")); - dialogWidget().statusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(IconSize(KIconLoader::Small))); + dialogWidget().statusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); } else { dialogWidget().statusText().setText(xi18nc("@label SMART disk status", "BAD")); - dialogWidget().statusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-warning")).pixmap(IconSize(KIconLoader::Small))); + dialogWidget().statusIcon().setPixmap(QIcon::fromTheme(QStringLiteral("dialog-warning")).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); } dialogWidget().modelName().setText(device().smartStatus().modelName()); dialogWidget().firmware().setText(device().smartStatus().firmware()); dialogWidget().serialNumber().setText(device().smartStatus().serial()); dialogWidget().temperature().setText(SmartStatus::tempToString(device().smartStatus().temp())); const QString badSectors = device().smartStatus().badSectors() > 0 ? QLocale().toString(device().smartStatus().badSectors()) : xi18nc("@label SMART number of bad sectors", "none"); dialogWidget().badSectors().setText(badSectors); dialogWidget().poweredOn().setText(KFormat().formatDuration(device().smartStatus().poweredOn())); dialogWidget().powerCycles().setText(QLocale().toString(device().smartStatus().powerCycles())); dialogWidget().overallAssessment().setText(SmartStatus::overallAssessmentToString(device().smartStatus().overall())); dialogWidget().selfTests().setText(SmartStatus::selfTestStatusToString(device().smartStatus().selfTestStatus())); dialogWidget().treeSmartAttributes().clear(); const QFont f = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); const QString size = f.pixelSize() != -1 ? QStringLiteral("%1px").arg(f.pixelSize()) : QStringLiteral("%1pt").arg(f.pointSize()); const QString st = QStringLiteral("").arg(f.family()).arg(size); for (const auto &a : device().smartStatus().attributes()) { QTreeWidgetItem* item = new QTreeWidgetItem( QStringList() << QLocale().toString(a.id()) << QStringLiteral("%1
%2").arg(a.name()).arg(st + a.desc() + QStringLiteral("
")) << (a.failureType() == SmartAttribute::FailureType::PreFailure ? xi18nc("@item:intable", "Pre-Failure") : xi18nc("@item:intable", "Old-Age")) << (a.updateType() == SmartAttribute::UpdateType::Online ? xi18nc("@item:intable", "Online") : xi18nc("@item:intable", "Offline")) << QLocale().toString(a.worst()) << QLocale().toString(a.current()) << QLocale().toString(a.threshold()) << a.raw() << a.assessmentToString() << a.value() ); item->setSizeHint(0, QSize(0, 64)); item->setToolTip(1, QTextDocumentFragment::fromHtml(a.desc()).toPlainText()); dialogWidget().treeSmartAttributes().addTopLevelItem(item); } } else dialogWidget().statusText().setText(xi18nc("@label", "(unknown)")); setMinimumSize(dialogWidget().size()); resize(dialogWidget().size()); } void SmartDialog::setupConnections() { connect(buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, this, &SmartDialog::saveSmartReport); connect(buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &SmartDialog::close); } QString SmartDialog::toHtml() const { QString rval; QTextStream s(&rval); if (device().smartStatus().status()) s << HtmlReport::tableLine(i18n("SMART status:"), xi18nc("@label SMART disk status", "good")); else s << HtmlReport::tableLine(i18n("SMART status:"), xi18nc("@label SMART disk status", "BAD")); const QString badSectors = device().smartStatus().badSectors() > 0 ? QLocale().toString(device().smartStatus().badSectors()) : i18nc("@label SMART number of bad sectors", "none"); s << HtmlReport::tableLine(i18n("Model:"), device().smartStatus().modelName()) << HtmlReport::tableLine(i18n("Serial number:"), device().smartStatus().serial()) << HtmlReport::tableLine(i18n("Firmware revision:"), device().smartStatus().firmware()) << HtmlReport::tableLine(i18n("Temperature:"), SmartStatus::tempToString(device().smartStatus().temp())) << HtmlReport::tableLine(i18n("Bad sectors:"), badSectors) << HtmlReport::tableLine(i18n("Powered on for:"), KFormat().formatDuration(device().smartStatus().poweredOn())) << HtmlReport::tableLine(i18n("Power cycles:"), QLocale().toString(device().smartStatus().powerCycles())) << HtmlReport::tableLine(i18n("Self tests:"), SmartStatus::selfTestStatusToString(device().smartStatus().selfTestStatus())) << HtmlReport::tableLine(i18n("Overall assessment:"), SmartStatus::overallAssessmentToString(device().smartStatus().overall())); s << "
"; if (device().smartStatus().isValid()) { const QFont f = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); const QString size = f.pixelSize() != -1 ? QStringLiteral("%1px").arg(f.pixelSize()) : QStringLiteral("%1pt").arg(f.pointSize()); const QString st = QStringLiteral("").arg(f.family()).arg(size); s << "\n"; for (const auto &a : device().smartStatus().attributes()) { s << "\n"; s << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n"; s << "\n"; } s << "
" << QLocale().toString(a.id()) << "" << QStringLiteral("%1
%2").arg(a.name()).arg(st + a.desc() + QStringLiteral("")) << "
" << (a.failureType() == SmartAttribute::FailureType::PreFailure ? xi18nc("@item:intable", "Pre-Failure") : xi18nc("@item:intable", "Old-Age")) << "" << (a.updateType() == SmartAttribute::UpdateType::Online ? xi18nc("@item:intable", "Online") : xi18nc("@item:intable", "Offline")) << "" << QLocale().toString(a.worst()) << "" << QLocale().toString(a.current()) << "" << QLocale().toString(a.threshold()) << "" << a.raw() << "" << a.assessmentToString() << "" << a.value() << "
\n"; } else s << "(unknown)"; s.flush(); return rval; } void SmartDialog::saveSmartReport() { const QUrl url = QFileDialog::getSaveFileUrl(); if (url.isEmpty()) return; QTemporaryFile tempFile; if (tempFile.open()) { QTextStream s(&tempFile); HtmlReport html; s << html.header() << toHtml() << html.footer(); tempFile.close(); KIO::CopyJob* job = KIO::move(QUrl::fromLocalFile(tempFile.fileName()), url, KIO::HideProgressInfo); job->exec(); if (job->error()) job->uiDelegate()->showErrorMessage(); } else KMessageBox::sorry(this, xi18nc("@info", "Could not create temporary file when trying to save to %1.", url.fileName()), xi18nc("@title:window", "Could Not Save SMART Report.")); } diff --git a/src/gui/treelog.cpp b/src/gui/treelog.cpp index 9cd0f6d..e0e593b 100644 --- a/src/gui/treelog.cpp +++ b/src/gui/treelog.cpp @@ -1,163 +1,163 @@ /************************************************************************* * Copyright (C) 2008, 2009 by Volker Lanz * * Copyright (C) 2016 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "gui/treelog.h" #include "gui/partitionmanagerwidget.h" #include "util/guihelpers.h" #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** Creates a new TreeLog instance. @param parent the parent widget */ TreeLog::TreeLog(QWidget* parent) : QWidget(parent), Ui::TreeLogBase() { setupUi(this); treeLog().header()->setContextMenuPolicy(Qt::CustomContextMenu); connect(treeLog().header(), &QHeaderView::customContextMenuRequested, this, &TreeLog::onHeaderContextMenu); } TreeLog::~TreeLog() { saveConfig(); } void TreeLog::init() { loadConfig(); } void TreeLog::loadConfig() { QList colWidths = Config::treeLogColumnWidths(); QList colPositions = Config::treeLogColumnPositions(); QList colVisible = Config::treeLogColumnVisible(); QHeaderView* header = treeLog().header(); for (int i = 0; i < treeLog().columnCount(); i++) { if (colPositions[0] != -1 && colPositions.size() > i) header->moveSection(header->visualIndex(i), colPositions[i]); if (colVisible[0] != -1 && colVisible.size() > i) treeLog().setColumnHidden(i, colVisible[i] == 0); if (colWidths[0] != -1 && colWidths.size() > i) treeLog().setColumnWidth(i, colWidths[i]); } } void TreeLog::saveConfig() const { QList colWidths; QList colPositions; QList colVisible; for (int i = 0; i < treeLog().columnCount(); i++) { colPositions.append(treeLog().header()->visualIndex(i)); colVisible.append(treeLog().isColumnHidden(i) ? 0 : 1); colWidths.append(treeLog().columnWidth(i)); } Config::setTreeLogColumnPositions(colPositions); Config::setTreeLogColumnVisible(colVisible); Config::setTreeLogColumnWidths(colWidths); Config::self()->save(); } void TreeLog::onHeaderContextMenu(const QPoint& pos) { showColumnsContextMenu(pos, treeLog()); } void TreeLog::onClearLog() { while (QTreeWidgetItem* item = treeLog().takeTopLevelItem(0)) delete item; } void TreeLog::onSaveLog() { const QUrl url = QFileDialog::getSaveFileUrl(); if (!url.isEmpty()) { QTemporaryFile tempFile; if (!tempFile.open()) { KMessageBox::error(this, xi18nc("@info", "Could not create temporary output file to save %1.", url.fileName()), xi18nc("@title:window", "Error Saving Log File")); return; } QTextStream stream(&tempFile); for (qint32 idx = 0; idx < treeLog().topLevelItemCount(); idx++) { QTreeWidgetItem* item = treeLog().topLevelItem(idx); stream << item->text(1) << ": " << item->text(2) << "\n"; } tempFile.close(); KIO::CopyJob* job = KIO::move(QUrl::fromLocalFile(tempFile.fileName()), url, KIO::HideProgressInfo); job->exec(); if (job->error()) job->uiDelegate()->showErrorMessage(); } } void TreeLog::onNewLogMessage(Log::Level logLevel, const QString& s) { static const QString icons[] = { QStringLiteral("tools-report-bug"), QStringLiteral("dialog-information"), QStringLiteral("dialog-warning"), QStringLiteral("dialog-error") }; qDebug() << s; if (static_cast(logLevel) >= Config::minLogLevel()) { QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setIcon(0, QIcon::fromTheme(icons[static_cast(logLevel)]).pixmap(IconSize(KIconLoader::Small))); + item->setIcon(0, QIcon::fromTheme(icons[static_cast(logLevel)]).pixmap(KIconLoader::global()->currentSize(KIconLoader::Small))); item->setText(1, QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss"))); item->setText(2, s); treeLog().addTopLevelItem(item); treeLog().scrollToBottom(); } }