diff --git a/README.md b/README.md index b7a2246..cf6f0c3 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,87 @@ -KDE Partition Manager -===================== - -### WARNING - -KDE Partition Manager is a potentially dangerous program for your data. It has -been tested carefully and there are currently no known bugs that could lead to -data loss, but nevertheless there is always a chance for an error to ocurr and -you might lose your data. - -### BACK UP YOUR DATA BEFORE USING THIS SOFTWARE! - -This software allows you to manage your disks, partitions and file systems: -Create, resize, delete, copy, backup and restore partitions with a large number -of supported file systems: - * ext2/3/4 - * Btrfs - * Linux swap - * Reiserfs - * F2FS - * NTFS - * FAT - * exFAT - * LUKS encryption support - * and more.... - -It is a KF5 application, so you will need KDE frameworks libraries to run it on -your computer. It also makes use of external programs to get its job done, so +# KDE Partition Manager + + + +KDE Partition Manager is an application to help you manage the disk devices, +partitions and file systems on your computer. It allows you to easily create, +copy, move, delete, resize without losing data, backup and restore partitions. + +A large number of file systems are also supported: +- ext2/3/4, Btrfs, Linux swap +- Reiserfs +- F2FS +- NTFS +- FAT +- exFAT +- LUKS encryption support +- and more.... + +:zap: **Back up your data before using this software**. KDE Partition Manager is +a potentially dangerous program for your data. It has been tested carefully and +there are currently no known bugs that could lead to data loss, but nevertheless +there is always a chance for an error to occur and you might lose your data. + + + +## Installation + +KDE Partition Manager is a KF5 application, so you will need the +[KDE frameworks](https://www.kde.org/products/frameworks/) libraries to run it +on your computer. Most modern OSs will install them as dependencies +for you when you use their default package manager as the installation method. + +It also makes use of external programs to get its job done, so you might have to install additional software (preferably packages from your distribution) to make use of all features and get full support for all file systems. -For quick install instructions see INSTALL. +The methods listed below for each major OS are based on executing the +installation commands on a terminal window. Alternatively, you can use +your OS' package management app. + +### Ubuntu + +``` +sudo apt install partitionmanager +``` + +### Debian + +As the `root` user: + +``` +apt install partitionmanager +``` + +### CentOS, Fedora, RHEL + +``` +sudo yum install kde-partitionmanager +``` + +### OpenSUSE +``` +sudo zypper install partitionmanager +``` + +### ArchLinux + +1. Enable the community repository on `/etc/pacman.conf`: + ``` + [community] + Include = /etc/pacman.d/mirrorlist + ``` +1. Install the `partitionmanager` xz package: + ``` + # pacman -Sy partitionmanager + ``` + +### From source + +See [INSTALL](INSTALL). + +## Changelog -For a list of changes since the previous release see CHANGES. +For a list of changes since the previous release see [CHANGES](CHANGES). diff --git a/src/gui/applyprogressdialog.h b/src/gui/applyprogressdialog.h index 0277faa..b838bb0 100644 --- a/src/gui/applyprogressdialog.h +++ b/src/gui/applyprogressdialog.h @@ -1,188 +1,187 @@ /************************************************************************* * Copyright (C) 2008, 2012 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 .* *************************************************************************/ -#if !defined(APPLYPROGRESSDIALOG_H) - +#ifndef APPLYPROGRESSDIALOG_H #define APPLYPROGRESSDIALOG_H #include #include #include #include class OperationRunner; class Operation; class Job; class ApplyProgressDialogWidget; class ApplyProgressDetailsWidget; class Report; class QDialogButtonBox; class QTreeWidgetItem; class QCloseEvent; class QKeyEvent; /** Show progress. The progress dialog telling the user about the progress of the Operations that are being applied. @author Volker Lanz */ class ApplyProgressDialog : public QDialog { Q_DISABLE_COPY(ApplyProgressDialog) public: ApplyProgressDialog(QWidget* parent, OperationRunner& orunner); ~ApplyProgressDialog(); public: void show(); Report& report() { Q_ASSERT(m_Report); /**< @return the Report object for this dialog */ return *m_Report; } const Report& report() const { Q_ASSERT(m_Report); /**< @return the Report object for this dialog */ return *m_Report; } protected: void onAllOpsFinished(); void onAllOpsCancelled(); void onAllOpsError(); void onCancelButton(); void onDetailsButton(); void onOkButton(); void onOpStarted(int num, Operation* op); void onOpFinished(int num, Operation* op); void onSecondElapsed(); void saveReport(); void browserReport(); void updateReportUnforced(); void updateReport(bool force = false); void onJobStarted(Job* job, Operation* op); void onJobFinished(Job* job, Operation* op); void toggleDetails(); void closeEvent(QCloseEvent* e) override; void keyPressEvent(QKeyEvent* e) override; void setupConnections(); const OperationRunner& operationRunner() const { return m_OperationRunner; } ApplyProgressDialogWidget & dialogWidget() { Q_ASSERT(m_ProgressDialogWidget); return *m_ProgressDialogWidget; } const ApplyProgressDialogWidget & dialogWidget() const { Q_ASSERT(m_ProgressDialogWidget); return *m_ProgressDialogWidget; } ApplyProgressDetailsWidget & detailsWidget() { Q_ASSERT(m_ProgressDetailsWidget); return *m_ProgressDetailsWidget; } const ApplyProgressDetailsWidget & detailsWidget() const { Q_ASSERT(m_ProgressDetailsWidget); return *m_ProgressDetailsWidget; } void setStatus(const QString& s); void setParentTitle(const QString& s); void addTaskOutput(int num, const Operation& op); QString opDesc(int num, const Operation& op) const; void resetReport(); void allOpsDone(const QString& msg); QTime& time() { return m_Time; } QTimer& timer() { return m_Timer; } const QTimer& timer() const { return m_Timer; } const QString& savedParentTitle() const { return m_SavedParentTitle; } void setCurrentOpItem(QTreeWidgetItem* item) { m_CurrentOpItem = item; } QTreeWidgetItem* currentOpItem() { return m_CurrentOpItem; } void setCurrentJobItem(QTreeWidgetItem* item) { m_CurrentJobItem = item; } QTreeWidgetItem* currentJobItem() { return m_CurrentJobItem; } int lastReportUpdate() const { return m_LastReportUpdate; } void setLastReportUpdate(int t) { m_LastReportUpdate = t; } static const QString& timeFormat() { return m_TimeFormat; } private: ApplyProgressDialogWidget* m_ProgressDialogWidget; ApplyProgressDetailsWidget* m_ProgressDetailsWidget; const OperationRunner& m_OperationRunner; Report* m_Report; QString m_SavedParentTitle; QTimer m_Timer; QTime m_Time; QTreeWidgetItem* m_CurrentOpItem; QTreeWidgetItem* m_CurrentJobItem; int m_LastReportUpdate; QDialogButtonBox* dialogButtonBox; QPushButton* okButton; QPushButton* cancelButton; QPushButton* detailsButton; static const QString m_TimeFormat; }; #endif diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index d84c95e..04767d2 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -1,1404 +1,1405 @@ /************************************************************************* * Copyright (C) 2008, 2009, 2010, 2012 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/mainwindow.h" #include "gui/infopane.h" #include "gui/applyprogressdialog.h" #include "gui/scanprogressdialog.h" #include "gui/createpartitiontabledialog.h" #include "gui/createvolumegroupdialog.h" #include "gui/resizevolumegroupdialog.h" #include "gui/filesystemsupportdialog.h" #include "gui/devicepropsdialog.h" #include "gui/smartdialog.h" #include "config/configureoptionsdialog.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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include /** Creates a new MainWindow instance. @param parent the parent widget */ MainWindow::MainWindow(QWidget* parent) : KXmlGuiWindow(parent), Ui::MainWindowBase(), m_OperationStack(new OperationStack(this)), m_OperationRunner(new OperationRunner(this, operationStack())), m_DeviceScanner(new DeviceScanner(this, operationStack())), m_ApplyProgressDialog(new ApplyProgressDialog(this, operationRunner())), m_ScanProgressDialog(new ScanProgressDialog(this)), m_StatusText(new QLabel(this)) { setupObjectNames(); setupUi(this); connect(&m_ListDevices->listDevices(), &QListWidget::customContextMenuRequested, this, &MainWindow::listDevicesContextMenuRequested); connect(&m_TreeLog->treeLog(), &QTreeWidget::customContextMenuRequested, this, &MainWindow::treeLogContextMenuRequested); connect(&m_ListOperations->listOperations(), &QListWidget::customContextMenuRequested, this, &MainWindow::listOperationsContextMenuRequested); init(); } void MainWindow::setupObjectNames() { m_OperationStack->setObjectName(QStringLiteral("m_OperationStack")); m_OperationRunner->setObjectName(QStringLiteral("m_OperationRunner")); m_DeviceScanner->setObjectName(QStringLiteral("m_DeviceScanner")); m_ApplyProgressDialog->setObjectName(QStringLiteral("m_ApplyProgressDialog")); m_ScanProgressDialog->setObjectName(QStringLiteral("m_ScanProgressDialog")); } void MainWindow::init() { treeLog().init(); connect(GlobalLog::instance(), &GlobalLog::newMessage, &treeLog(), &TreeLog::onNewLogMessage); setupActions(); setupStatusBar(); setupConnections(); listDevices().setActionCollection(actionCollection()); listOperations().setActionCollection(actionCollection()); setupGUI(); loadConfig(); show(); ExternalCommand::setParentWidget(this); pmWidget().init(&operationStack()); scanDevices(); } void MainWindow::closeEvent(QCloseEvent* event) { if (applyProgressDialog().isVisible()) { event->ignore(); return; } if (operationStack().size() > 0) { if (KMessageBox::warningContinueCancel(this, xi18ncp("@info", "Do you really want to quit the application?There is still an operation pending.", "Do you really want to quit the application?There are still %1 operations pending.", operationStack().size()), xi18nc("@title:window", "Discard Pending Operations and Quit?"), KGuiItem(xi18nc("@action:button", "Quit %1", QGuiApplication::applicationDisplayName()), QStringLiteral("arrow-right")), KStandardGuiItem::cancel(), QStringLiteral("reallyQuit")) == KMessageBox::Cancel) { event->ignore(); return; } } saveConfig(); KXmlGuiWindow::closeEvent(event); ExternalCommand::stopHelper(); + delete m_ApplyProgressDialog; } void MainWindow::changeEvent(QEvent* event) { if ((event->type() == QEvent::ActivationChange || event->type() == QEvent::WindowStateChange) && event->spontaneous() && isActiveWindow()) { QWidget* w = nullptr; if (applyProgressDialog().isVisible()) w = &applyProgressDialog(); else if (scanProgressDialog().isVisible()) w = &scanProgressDialog(); if (w != nullptr) { w->activateWindow(); w->raise(); w->setFocus(); } } KXmlGuiWindow::changeEvent(event); } void MainWindow::setupActions() { // File actions KStandardAction::quit(this, &MainWindow::close, actionCollection()); // Edit actions QAction* undoOperation = actionCollection()->addAction(QStringLiteral("undoOperation")); connect(undoOperation, &QAction::triggered, this, &MainWindow::onUndoOperation); undoOperation->setEnabled(false); undoOperation->setText(xi18nc("@action:inmenu", "Undo")); undoOperation->setToolTip(xi18nc("@info:tooltip", "Undo the last operation")); undoOperation->setStatusTip(xi18nc("@info:status", "Remove the last operation from the list.")); actionCollection()->setDefaultShortcut(undoOperation, QKeySequence(Qt::CTRL + Qt::Key_Z)); undoOperation->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* clearAllOperations = actionCollection()->addAction(QStringLiteral("clearAllOperations")); connect(clearAllOperations, &QAction::triggered, this, &MainWindow::onClearAllOperations); clearAllOperations->setEnabled(false); clearAllOperations->setText(xi18nc("@action:inmenu clear the list of operations", "Clear")); clearAllOperations->setToolTip(xi18nc("@info:tooltip", "Clear all operations")); clearAllOperations->setStatusTip(xi18nc("@info:status", "Empty the list of pending operations.")); clearAllOperations->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* applyAllOperations = actionCollection()->addAction(QStringLiteral("applyAllOperations")); connect(applyAllOperations, &QAction::triggered, this, &MainWindow::onApplyAllOperations); applyAllOperations->setEnabled(false); applyAllOperations->setText(xi18nc("@action:inmenu apply all operations", "Apply")); applyAllOperations->setToolTip(xi18nc("@info:tooltip", "Apply all operations")); applyAllOperations->setStatusTip(xi18nc("@info:status", "Apply the pending operations in the list.")); applyAllOperations->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply")).pixmap(IconSize(KIconLoader::Toolbar))); // Device actions QAction* createNewPartitionTable = actionCollection()->addAction(QStringLiteral("createNewPartitionTable")); connect(createNewPartitionTable, &QAction::triggered, this, &MainWindow::onCreateNewPartitionTable); createNewPartitionTable->setEnabled(false); createNewPartitionTable->setText(xi18nc("@action:inmenu", "New Partition Table")); createNewPartitionTable->setToolTip(xi18nc("@info:tooltip", "Create a new partition table")); createNewPartitionTable->setStatusTip(xi18nc("@info:status", "Create a new and empty partition table on a device.")); actionCollection()->setDefaultShortcut(createNewPartitionTable, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_N)); createNewPartitionTable->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* exportPartitionTable = actionCollection()->addAction(QStringLiteral("exportPartitionTable")); connect(exportPartitionTable, &QAction::triggered, this, &MainWindow::onExportPartitionTable); exportPartitionTable->setEnabled(false); exportPartitionTable->setText(xi18nc("@action:inmenu", "Export Partition Table")); exportPartitionTable->setToolTip(xi18nc("@info:tooltip", "Export a partition table")); exportPartitionTable->setStatusTip(xi18nc("@info:status", "Export the device's partition table to a text file.")); exportPartitionTable->setIcon(QIcon::fromTheme(QStringLiteral("document-export")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* importPartitionTable = actionCollection()->addAction(QStringLiteral("importPartitionTable")); connect(importPartitionTable, &QAction::triggered, this, &MainWindow::onImportPartitionTable); importPartitionTable->setEnabled(false); importPartitionTable->setText(xi18nc("@action:inmenu", "Import Partition Table")); importPartitionTable->setToolTip(xi18nc("@info:tooltip", "Import a partition table")); importPartitionTable->setStatusTip(xi18nc("@info:status", "Import a partition table from a text file.")); importPartitionTable->setIcon(QIcon::fromTheme(QStringLiteral("document-import")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* removeVolumeGroup = actionCollection()->addAction(QStringLiteral("removeVolumeGroup")); connect(removeVolumeGroup, &QAction::triggered, this, &MainWindow::onRemoveVolumeGroup); removeVolumeGroup->setEnabled(false); removeVolumeGroup->setVisible(false); removeVolumeGroup->setText(i18nc("@action:inmenu", "Remove Volume Group")); removeVolumeGroup->setToolTip(i18nc("@info:tooltip", "Remove selected Volume Group")); removeVolumeGroup->setStatusTip(i18nc("@info:status", "Remove selected Volume Group.")); //actionCollection()->setDefaultShortcut(removeVolumeGroup, QKeySequence(/*SHORTCUT KEY HERE*/)); removeVolumeGroup->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* resizeVolumeGroup = actionCollection()->addAction(QStringLiteral("resizeVolumeGroup")); connect(resizeVolumeGroup, &QAction::triggered, this, &MainWindow::onResizeVolumeGroup); resizeVolumeGroup->setEnabled(false); resizeVolumeGroup->setVisible(false); resizeVolumeGroup->setText(i18nc("@action:inmenu", "Resize Volume Group")); resizeVolumeGroup->setToolTip(i18nc("@info:tooltip", "Resize selected Volume Group")); resizeVolumeGroup->setStatusTip(i18nc("@info:status", "Extend or reduce selected Volume Group.")); //actionCollection()->setDefaultShortcut(resizeVolumeGroup, QKeySequence(/*SHORTCUT KEY HERE*/)); resizeVolumeGroup->setIcon(QIcon::fromTheme(QStringLiteral("arrow-right-double")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* activateRAID = actionCollection()->addAction(QStringLiteral("activateRAID")); connect(activateRAID, &QAction::triggered, this, &MainWindow::onActivateRAID); activateRAID->setEnabled(false); activateRAID->setVisible(false); activateRAID->setText(i18nc("@action:inmenu", "Activate RAID")); activateRAID->setToolTip(i18nc("@info:tooltip", "Activate selected RAID device")); activateRAID->setStatusTip(i18nc("@info:status", "Activate selected RAID device")); activateRAID->setIcon(QIcon::fromTheme(QStringLiteral("answer")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* deactivateVolumeGroup = actionCollection()->addAction(QStringLiteral("deactivateVolumeGroup")); connect(deactivateVolumeGroup, &QAction::triggered, this, &MainWindow::onDeactivateVolumeGroup); deactivateVolumeGroup->setEnabled(false); deactivateVolumeGroup->setVisible(false); deactivateVolumeGroup->setText(i18nc("@action:inmenu", "Deactivate Volume Group")); deactivateVolumeGroup->setToolTip(i18nc("@info:tooltip", "Deactivate selected Volume Group")); deactivateVolumeGroup->setStatusTip(i18nc("@info:status", "Deactivate selected Volume Group before unplugging removable devices.")); deactivateVolumeGroup->setIcon(QIcon::fromTheme(QStringLiteral("media-eject")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* smartStatusDevice = actionCollection()->addAction(QStringLiteral("smartStatusDevice")); connect(smartStatusDevice, &QAction::triggered, this, &MainWindow::onSmartStatusDevice); smartStatusDevice->setEnabled(false); smartStatusDevice->setText(xi18nc("@action:inmenu", "SMART Status")); smartStatusDevice->setToolTip(xi18nc("@info:tooltip", "Show SMART status")); smartStatusDevice->setStatusTip(xi18nc("@info:status", "Show the device's SMART status if supported")); QAction* propertiesDevice = actionCollection()->addAction(QStringLiteral("propertiesDevice")); connect(propertiesDevice, &QAction::triggered, [this] {onPropertiesDevice({});}); propertiesDevice->setEnabled(false); propertiesDevice->setText(xi18nc("@action:inmenu", "Properties")); propertiesDevice->setToolTip(xi18nc("@info:tooltip", "Show device properties dialog")); propertiesDevice->setStatusTip(xi18nc("@info:status", "View and modify device properties")); propertiesDevice->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")).pixmap(IconSize(KIconLoader::Toolbar))); // Partition actions QAction* newPartition = actionCollection()->addAction(QStringLiteral("newPartition")); connect(newPartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onNewPartition); newPartition->setEnabled(false); newPartition->setText(xi18nc("@action:inmenu create a new partition", "New")); newPartition->setToolTip(xi18nc("@info:tooltip", "New partition")); newPartition->setStatusTip(xi18nc("@info:status", "Create a new partition.")); actionCollection()->setDefaultShortcut(newPartition, QKeySequence(Qt::CTRL + Qt::Key_N)); newPartition->setIcon(QIcon::fromTheme(QStringLiteral("document-new")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* resizePartition = actionCollection()->addAction(QStringLiteral("resizePartition")); connect(resizePartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onResizePartition); resizePartition->setEnabled(false); resizePartition->setText(xi18nc("@action:inmenu", "Resize/Move")); resizePartition->setToolTip(xi18nc("@info:tooltip", "Resize or move partition")); resizePartition->setStatusTip(xi18nc("@info:status", "Shrink, grow or move an existing partition.")); actionCollection()->setDefaultShortcut(resizePartition, QKeySequence(Qt::CTRL + Qt::Key_R)); resizePartition->setIcon(QIcon::fromTheme(QStringLiteral("arrow-right-double")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* deletePartition = actionCollection()->addAction(QStringLiteral("deletePartition")); connect(deletePartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onDeletePartition); deletePartition->setEnabled(false); deletePartition->setText(xi18nc("@action:inmenu", "Delete")); deletePartition->setToolTip(xi18nc("@info:tooltip", "Delete partition")); deletePartition->setStatusTip(xi18nc("@info:status", "Delete a partition.")); actionCollection()->setDefaultShortcut(deletePartition, QKeySequence::Delete); deletePartition->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* shredPartition = actionCollection()->addAction(QStringLiteral("shredPartition")); connect(shredPartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onShredPartition); shredPartition->setEnabled(false); shredPartition->setText(xi18nc("@action:inmenu", "Shred")); shredPartition->setToolTip(xi18nc("@info:tooltip", "Shred partition")); shredPartition->setStatusTip(xi18nc("@info:status", "Shred a partition so that its contents cannot be restored.")); actionCollection()->setDefaultShortcut(shredPartition, QKeySequence(Qt::SHIFT + Qt::Key_Delete)); shredPartition->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete-shred")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* copyPartition = actionCollection()->addAction(QStringLiteral("copyPartition")); connect(copyPartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onCopyPartition); copyPartition->setEnabled(false); copyPartition->setText(xi18nc("@action:inmenu", "Copy")); copyPartition->setToolTip(xi18nc("@info:tooltip", "Copy partition")); copyPartition->setStatusTip(xi18nc("@info:status", "Copy an existing partition.")); actionCollection()->setDefaultShortcut(copyPartition, QKeySequence(Qt::CTRL + Qt::Key_C)); copyPartition->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* pastePartition = actionCollection()->addAction(QStringLiteral("pastePartition")); connect(pastePartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onPastePartition); pastePartition->setEnabled(false); pastePartition->setText(xi18nc("@action:inmenu", "Paste")); pastePartition->setToolTip(xi18nc("@info:tooltip", "Paste partition")); pastePartition->setStatusTip(xi18nc("@info:status", "Paste a copied partition.")); actionCollection()->setDefaultShortcut(pastePartition, QKeySequence(Qt::CTRL + Qt::Key_V)); pastePartition->setIcon(QIcon::fromTheme(QStringLiteral("edit-paste")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* editMountPoint = actionCollection()->addAction(QStringLiteral("editMountPoint")); connect(editMountPoint, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onEditMountPoint); editMountPoint->setEnabled(false); editMountPoint->setText(xi18nc("@action:inmenu", "Edit Mount Point")); editMountPoint->setToolTip(xi18nc("@info:tooltip", "Edit mount point")); editMountPoint->setStatusTip(xi18nc("@info:status", "Edit a partition's mount point and options.")); QAction* mountPartition = actionCollection()->addAction(QStringLiteral("mountPartition")); connect(mountPartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onMountPartition); mountPartition->setEnabled(false); mountPartition->setText(xi18nc("@action:inmenu", "Mount")); mountPartition->setToolTip(xi18nc("@info:tooltip", "Mount or unmount partition")); mountPartition->setStatusTip(xi18nc("@info:status", "Mount or unmount a partition.")); QAction* decryptPartition = actionCollection()->addAction(QStringLiteral("decryptPartition")); connect(decryptPartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onDecryptPartition); decryptPartition->setEnabled(false); decryptPartition->setText(xi18nc("@action:inmenu", "Unlock")); decryptPartition->setToolTip(xi18nc("@info:tooltip", "Unlock or lock encrypted partition")); decryptPartition->setStatusTip(xi18nc("@info:status", "Unlock or lock encrypted partition.")); QAction* checkPartition = actionCollection()->addAction(QStringLiteral("checkPartition")); connect(checkPartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onCheckPartition); checkPartition->setEnabled(false); checkPartition->setText(xi18nc("@action:inmenu", "Check")); checkPartition->setToolTip(xi18nc("@info:tooltip", "Check partition")); checkPartition->setStatusTip(xi18nc("@info:status", "Check a filesystem on a partition for errors.")); checkPartition->setIcon(QIcon::fromTheme(QStringLiteral("flag")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* propertiesPartition = actionCollection()->addAction(QStringLiteral("propertiesPartition")); connect(propertiesPartition, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onPropertiesPartition); propertiesPartition->setEnabled(false); propertiesPartition->setText(xi18nc("@action:inmenu", "Properties")); propertiesPartition->setToolTip(xi18nc("@info:tooltip", "Show partition properties dialog")); propertiesPartition->setStatusTip(xi18nc("@info:status", "View and modify partition properties (label, partition flags, etc.)")); propertiesPartition->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* backup = actionCollection()->addAction(QStringLiteral("backupPartition")); connect(backup, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onBackupPartition); backup->setEnabled(false); backup->setText(xi18nc("@action:inmenu", "Backup")); backup->setToolTip(xi18nc("@info:tooltip", "Backup partition")); backup->setStatusTip(xi18nc("@info:status", "Backup a partition to an image file.")); backup->setIcon(QIcon::fromTheme(QStringLiteral("document-export")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* restore = actionCollection()->addAction(QStringLiteral("restorePartition")); connect(restore, &QAction::triggered, &pmWidget(), &PartitionManagerWidget::onRestorePartition); restore->setEnabled(false); restore->setText(xi18nc("@action:inmenu", "Restore")); restore->setToolTip(xi18nc("@info:tooltip", "Restore partition")); restore->setStatusTip(xi18nc("@info:status", "Restore a partition from an image file.")); restore->setIcon(QIcon::fromTheme(QStringLiteral("document-import")).pixmap(IconSize(KIconLoader::Toolbar))); // Tools actions QAction* createVolumeGroup = actionCollection()->addAction(QStringLiteral("createVolumeGroup")); connect(createVolumeGroup, &QAction::triggered, this, &MainWindow::onCreateNewVolumeGroup); createVolumeGroup->setEnabled(false); createVolumeGroup->setText(i18nc("@action:inmenu", "New Volume Group")); createVolumeGroup->setToolTip(i18nc("@info:tooltip", "Create a new LVM Volume Group")); createVolumeGroup->setStatusTip(i18nc("@info:status", "Create a new LVM Volume Group as a device.")); actionCollection()->setDefaultShortcut(createVolumeGroup, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_L)); createVolumeGroup->setIcon(QIcon::fromTheme(QStringLiteral("document-new")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* fileSystemSupport = actionCollection()->addAction(QStringLiteral("fileSystemSupport")); connect(fileSystemSupport, &QAction::triggered, this, &MainWindow::onFileSystemSupport); fileSystemSupport->setText(xi18nc("@action:inmenu", "File System Support")); fileSystemSupport->setToolTip(xi18nc("@info:tooltip", "View file system support information")); fileSystemSupport->setStatusTip(xi18nc("@info:status", "Show information about supported file systems.")); QAction* refreshDevices = actionCollection()->addAction(QStringLiteral("refreshDevices")); connect(refreshDevices, &QAction::triggered, this, &MainWindow::onRefreshDevices); refreshDevices->setText(xi18nc("@action:inmenu refresh list of devices", "Refresh Devices")); refreshDevices->setToolTip(xi18nc("@info:tooltip", "Refresh all devices")); refreshDevices->setStatusTip(xi18nc("@info:status", "Renew the devices list.")); actionCollection()->setDefaultShortcut(refreshDevices, Qt::Key_F5); refreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")).pixmap(IconSize(KIconLoader::Toolbar))); // Settings Actions actionCollection()->addAction(QStringLiteral("toggleDockDevices"), dockDevices().toggleViewAction()); actionCollection()->addAction(QStringLiteral("toggleDockOperations"), dockOperations().toggleViewAction()); actionCollection()->addAction(QStringLiteral("toggleDockInformation"), dockInformation().toggleViewAction()); actionCollection()->addAction(QStringLiteral("toggleDockLog"), dockLog().toggleViewAction()); KStandardAction::preferences(this, &MainWindow::onConfigureOptions, actionCollection()); // Log Actions QAction* clearLog = actionCollection()->addAction(QStringLiteral("clearLog")); connect(clearLog, &QAction::triggered, &treeLog(), &TreeLog::onClearLog); clearLog->setText(xi18nc("@action:inmenu", "Clear Log")); clearLog->setToolTip(xi18nc("@info:tooltip", "Clear the log output")); clearLog->setStatusTip(xi18nc("@info:status", "Clear the log output panel.")); clearLog->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-list")).pixmap(IconSize(KIconLoader::Toolbar))); QAction* saveLog = actionCollection()->addAction(QStringLiteral("saveLog")); connect(saveLog, &QAction::triggered, &treeLog(), &TreeLog::onSaveLog); saveLog->setText(xi18nc("@action:inmenu", "Save Log")); saveLog->setToolTip(xi18nc("@info:tooltip", "Save the log output")); saveLog->setStatusTip(xi18nc("@info:status", "Save the log output to a file.")); saveLog->setIcon(QIcon::fromTheme(QStringLiteral("document-save")).pixmap(IconSize(KIconLoader::Toolbar))); // Help Actions QAction* aboutKPMcore = actionCollection()->addAction(QStringLiteral("aboutKPMcore")); connect(aboutKPMcore, &QAction::triggered, this, &MainWindow::onShowAboutKPMcore); aboutKPMcore->setText(xi18nc("@action:inmenu", "About KPMcore Library")); aboutKPMcore->setToolTip(xi18nc("@info:tooltip", "Show About KPMcore dialog")); aboutKPMcore->setStatusTip(xi18nc("@info:status", "Show About KPMcore dialog.")); aboutKPMcore->setIcon(QIcon::fromTheme(QStringLiteral("partitionmanager")).pixmap(IconSize(KIconLoader::Toolbar))); } void MainWindow::setupConnections() { connect(&listDevices(), &ListDevices::selectionChanged, &pmWidget(), qOverload(&PartitionManagerWidget::setSelectedDevice)); connect(&listDevices(), &ListDevices::deviceDoubleClicked, this, &MainWindow::onPropertiesDevice); } void MainWindow::setupStatusBar() { statusBar()->addWidget(&statusText()); } void MainWindow::loadConfig() { if (Config::firstRun()) { dockLog().setVisible(false); dockInformation().setVisible(false); } PartitionAlignment::setSectorAlignment(Config::sectorAlignment()); } void MainWindow::saveConfig() const { Config::setFirstRun(false); Config::self()->save(); } void MainWindow::enableActions() { actionCollection()->action(QStringLiteral("createNewPartitionTable")) ->setEnabled(CreatePartitionTableOperation::canCreate(pmWidget().selectedDevice())); actionCollection()->action(QStringLiteral("createNewPartitionTable")) ->setVisible(pmWidget().selectedDevice() && (pmWidget().selectedDevice()->type() == Device::Type::Disk_Device || pmWidget().selectedDevice()->type() == Device::Type::SoftwareRAID_Device)); actionCollection()->action(QStringLiteral("exportPartitionTable")) ->setEnabled(pmWidget().selectedDevice() && pmWidget().selectedDevice()->partitionTable() && operationStack().size() == 0); actionCollection()->action(QStringLiteral("importPartitionTable")) ->setEnabled(CreatePartitionTableOperation::canCreate(pmWidget().selectedDevice())); actionCollection()->action(QStringLiteral("smartStatusDevice")) ->setEnabled(pmWidget().selectedDevice() != nullptr && pmWidget().selectedDevice()->type() == Device::Type::Disk_Device && pmWidget().selectedDevice()->smartStatus().isValid()); actionCollection()->action(QStringLiteral("smartStatusDevice")) ->setVisible(pmWidget().selectedDevice() != nullptr && pmWidget().selectedDevice()->type() == Device::Type::Disk_Device); actionCollection()->action(QStringLiteral("propertiesDevice")) ->setEnabled(pmWidget().selectedDevice() != nullptr); actionCollection()->action(QStringLiteral("undoOperation")) ->setEnabled(operationStack().size() > 0); actionCollection()->action(QStringLiteral("clearAllOperations")) ->setEnabled(operationStack().size() > 0); actionCollection()->action(QStringLiteral("applyAllOperations")) ->setEnabled(operationStack().size() > 0); const bool readOnly = pmWidget().selectedDevice() == nullptr || pmWidget().selectedDevice()->partitionTable() == nullptr || pmWidget().selectedDevice()->partitionTable()->isReadOnly(); actionCollection()->action(QStringLiteral("createVolumeGroup")) ->setEnabled(CreateVolumeGroupOperation::canCreate()); bool vgDevice = pmWidget().selectedDevice() && (pmWidget().selectedDevice()->type() == Device::Type::LVM_Device || pmWidget().selectedDevice()->type() == Device::Type::SoftwareRAID_Device); bool removable = false; if (vgDevice) removable = RemoveVolumeGroupOperation::isRemovable(dynamic_cast(pmWidget().selectedDevice())); actionCollection()->action(QStringLiteral("removeVolumeGroup"))->setEnabled(removable); actionCollection()->action(QStringLiteral("removeVolumeGroup"))->setVisible(vgDevice); bool isRaid = vgDevice && pmWidget().selectedDevice()->type() == Device::Type::SoftwareRAID_Device; bool canActivateRAID = isRaid && static_cast< SoftwareRAID* >(pmWidget().selectedDevice())->status() == SoftwareRAID::Status::Inactive; actionCollection()->action(QStringLiteral("activateRAID"))->setEnabled(canActivateRAID); actionCollection()->action(QStringLiteral("activateRAID"))->setVisible(isRaid); bool deactivatable = vgDevice ? DeactivateVolumeGroupOperation::isDeactivatable(dynamic_cast(pmWidget().selectedDevice())) : false; actionCollection()->action(QStringLiteral("deactivateVolumeGroup"))->setEnabled(deactivatable); actionCollection()->action(QStringLiteral("deactivateVolumeGroup"))->setVisible(vgDevice); bool canResizeVG = vgDevice; if (isRaid) canResizeVG = static_cast(pmWidget().selectedDevice())->status() == SoftwareRAID::Status::Active; actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setEnabled(canResizeVG); actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setVisible(canResizeVG); const Partition* part = pmWidget().selectedPartition(); actionCollection()->action(QStringLiteral("newPartition")) ->setEnabled(!readOnly && NewOperation::canCreateNew(part)); const bool canResize = ResizeOperation::canGrow(part) || ResizeOperation::canShrink(part) || ResizeOperation::canMove(part); actionCollection()->action(QStringLiteral("resizePartition")) ->setEnabled(!readOnly && canResize); actionCollection()->action(QStringLiteral("copyPartition")) ->setEnabled(CopyOperation::canCopy(part)); actionCollection()->action(QStringLiteral("deletePartition")) ->setEnabled(!readOnly && DeleteOperation::canDelete(part)); actionCollection()->action(QStringLiteral("shredPartition")) ->setEnabled(!readOnly && DeleteOperation::canDelete(part)); actionCollection()->action(QStringLiteral("pastePartition")) ->setEnabled(!readOnly && CopyOperation::canPaste(part, pmWidget().clipboardPartition())); actionCollection()->action(QStringLiteral("propertiesPartition")) ->setEnabled(part != nullptr); actionCollection()->action(QStringLiteral("editMountPoint")) ->setEnabled(part && !part->isMounted() && part->fileSystem().canMount(part->deviceNode(), QStringLiteral("/"))); actionCollection()->action(QStringLiteral("mountPartition")) ->setEnabled(part && (part->canMount() || part->canUnmount())); if (part != nullptr) actionCollection()->action(QStringLiteral("mountPartition")) ->setText(part->isMounted() ? part->fileSystem().unmountTitle() : part->fileSystem().mountTitle()); if (part && part->roles().has(PartitionRole::Luks)) { const FileSystem& fsRef = part->fileSystem(); const FS::luks* luksFs = dynamic_cast(&fsRef); actionCollection()->action(QStringLiteral("decryptPartition")) ->setVisible(true); actionCollection()->action(QStringLiteral("decryptPartition")) ->setEnabled(luksFs && !operationStack().contains(part) && (luksFs->canCryptOpen(part->partitionPath()) || luksFs->canCryptClose(part->partitionPath()))); if (luksFs) { actionCollection()->action(QStringLiteral("decryptPartition")) ->setText(luksFs->isCryptOpen() ? luksFs->cryptCloseTitle() : luksFs->cryptOpenTitle()); } } else { actionCollection()->action(QStringLiteral("decryptPartition")) ->setEnabled(false); actionCollection()->action(QStringLiteral("decryptPartition")) ->setVisible(false); } actionCollection()->action(QStringLiteral("checkPartition")) ->setEnabled(!readOnly && CheckOperation::canCheck(part)); actionCollection()->action(QStringLiteral("backupPartition")) ->setEnabled(BackupOperation::canBackup(part)); actionCollection()->action(QStringLiteral("restorePartition")) ->setEnabled(RestoreOperation::canRestore(part)); } void MainWindow::on_m_ApplyProgressDialog_finished() { scanDevices(); } void MainWindow::on_m_OperationStack_operationsChanged() { listOperations().updateOperations(operationStack().operations()); pmWidget().updatePartitions(); enableActions(); // this will make sure that the info pane gets updated on_m_PartitionManagerWidget_selectedPartitionChanged(pmWidget().selectedPartition()); statusText().setText(xi18ncp("@info:status", "One pending operation", "%1 pending operations", operationStack().size())); } void MainWindow::on_m_OperationStack_devicesChanged() { QReadLocker lockDevices(&operationStack().lock()); listDevices().updateDevices(operationStack().previewDevices()); if (pmWidget().selectedDevice()) infoPane().showDevice(dockWidgetArea(&dockInformation()), *pmWidget().selectedDevice()); else infoPane().clear(); updateWindowTitle(); } void MainWindow::on_m_DockInformation_dockLocationChanged(Qt::DockWidgetArea) { on_m_PartitionManagerWidget_selectedPartitionChanged(pmWidget().selectedPartition()); } void MainWindow::updateWindowTitle() { QString title; if (pmWidget().selectedDevice()) title = pmWidget().selectedDevice()->deviceNode(); setWindowTitle(title); } void MainWindow::listOperationsContextMenuRequested(const QPoint& pos) { QMenu* menu = static_cast(guiFactory()->container(QStringLiteral("edit"), this)); if (menu) menu->exec(m_ListOperations->listOperations().viewport()->mapToGlobal(pos)); } void MainWindow::treeLogContextMenuRequested(const QPoint& pos) { QMenu* menu = static_cast(guiFactory()->container(QStringLiteral("log"), this)); if (menu) menu->exec(m_TreeLog->treeLog().viewport()->mapToGlobal(pos)); } void MainWindow::listDevicesContextMenuRequested(const QPoint& pos) { QMenu* menu = static_cast(guiFactory()->container(QStringLiteral("device"), this)); if (menu) menu->exec(m_ListDevices->listDevices().viewport()->mapToGlobal(pos)); } void MainWindow::on_m_PartitionManagerWidget_contextMenuRequested(const QPoint& pos) { QMenu* menu = nullptr; if (pmWidget().selectedPartition() == nullptr) { if (pmWidget().selectedDevice() != nullptr) menu = static_cast(guiFactory()->container(QStringLiteral("device"), this)); } else menu = static_cast(guiFactory()->container(QStringLiteral("partition"), this)); if (menu) menu->exec(pos); } void MainWindow::on_m_PartitionManagerWidget_deviceDoubleClicked(const Device*) { actionCollection()->action(QStringLiteral("propertiesDevice"))->trigger(); } void MainWindow::on_m_PartitionManagerWidget_partitionDoubleClicked(const Partition*) { actionCollection()->action(QStringLiteral("propertiesPartition"))->trigger(); } void MainWindow::on_m_PartitionManagerWidget_selectedPartitionChanged(const Partition* p) { if (p) infoPane().showPartition(dockWidgetArea(&dockInformation()), *p); else if (pmWidget().selectedDevice()) infoPane().showDevice(dockWidgetArea(&dockInformation()), *pmWidget().selectedDevice()); else infoPane().clear(); updateWindowTitle(); enableActions(); } void MainWindow::scanDevices() { Log(Log::Level::information) << xi18nc("@info:progress", "Using backend plugin: %1 (%2)", CoreBackendManager::self()->backend()->id(), CoreBackendManager::self()->backend()->version()); Log() << xi18nc("@info:progress", "Scanning devices..."); // remember the currently selected device's node setSavedSelectedDeviceNode(pmWidget().selectedDevice() ? pmWidget().selectedDevice()->deviceNode() : QString()); pmWidget().clear(); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); scanProgressDialog().setEnabled(true); scanProgressDialog().show(); deviceScanner().start(); } void MainWindow::on_m_DeviceScanner_progress(const QString& deviceNode, int percent) { scanProgressDialog().setProgress(percent); scanProgressDialog().setDeviceName(deviceNode); } void MainWindow::on_m_DeviceScanner_finished() { QReadLocker lockDevices(&operationStack().lock()); scanProgressDialog().setProgress(100); if (!operationStack().previewDevices().isEmpty()) pmWidget().setSelectedDevice(operationStack().previewDevices()[0]); pmWidget().updatePartitions(); Log() << xi18nc("@info:progress", "Scan finished."); QApplication::restoreOverrideCursor(); // try to set the seleted device, either from the saved one or just select the // first device if (!listDevices().setSelectedDevice(savedSelectedDeviceNode()) && !operationStack().previewDevices().isEmpty()) listDevices().setSelectedDevice(operationStack().previewDevices()[0]->deviceNode()); updateSeletedDeviceMenu(); checkFileSystemSupport(); } void MainWindow::updateSeletedDeviceMenu() { QMenu* devicesMenu = static_cast(guiFactory()->container(QStringLiteral("selectedDevice"), this)); if (!devicesMenu) return; devicesMenu->clear(); devicesMenu->setEnabled(!operationStack().previewDevices().isEmpty()); const auto previewDevices = operationStack().previewDevices(); for (auto const &d : previewDevices) { QAction* action = new QAction(d->prettyName(), devicesMenu); action->setCheckable(true); action->setChecked(d->deviceNode() == pmWidget().selectedDevice()->deviceNode()); action->setData(d->deviceNode()); connect(action, &QAction::triggered, this, &MainWindow::onSelectedDeviceMenuTriggered); devicesMenu->addAction(action); } } void MainWindow::onSelectedDeviceMenuTriggered(bool) { QAction* action = qobject_cast(sender()); QMenu* devicesMenu = static_cast(guiFactory()->container(QStringLiteral("selectedDevice"), this)); if (action == nullptr || action->parent() != devicesMenu || !devicesMenu) return; const auto children = devicesMenu->findChildren(); for (auto &entry : children) entry->setChecked(entry == action); listDevices().setSelectedDevice(action->data().toString()); } void MainWindow::on_m_ListDevices_selectionChanged(const QString& device_node) { QMenu* devicesMenu = static_cast(guiFactory()->container(QStringLiteral("selectedDevice"), this)); if (!devicesMenu) return; const auto children = devicesMenu->findChildren(); for (auto &entry : children) entry->setChecked(entry->data().toString() == device_node); } void MainWindow::onRefreshDevices() { if (operationStack().size() == 0 || KMessageBox::warningContinueCancel(this, xi18nc("@info", "Do you really want to rescan the devices?" "This will also clear the list of pending operations."), xi18nc("@title:window", "Really Rescan the Devices?"), KGuiItem(xi18nc("@action:button", "Rescan Devices"), QStringLiteral("arrow-right")), KStandardGuiItem::cancel(), QStringLiteral("reallyRescanDevices")) == KMessageBox::Continue) { scanDevices(); } } void MainWindow::onApplyAllOperations() { QStringList opList; const auto operations = operationStack().operations(); for (const auto &op : operations) opList.append(op->description()); if (KMessageBox::warningContinueCancelList(this, xi18nc("@info", "Do you really want to apply the pending operations listed below?" "This will permanently modify your disks."), opList, xi18nc("@title:window", "Apply Pending Operations?"), KGuiItem(xi18nc("@action:button", "Apply Pending Operations"), QStringLiteral("arrow-right")), KStandardGuiItem::cancel()) == KMessageBox::Continue) { Log() << xi18nc("@info:status", "Applying operations..."); applyProgressDialog().show(); operationRunner().setReport(&applyProgressDialog().report()); // Undo all operations so the runner has a defined starting point for (int i = operationStack().operations().size() - 1; i >= 0; i--) { operationStack().operations()[i]->undo(); operationStack().operations()[i]->setStatus(Operation::StatusNone); } pmWidget().updatePartitions(); operationRunner().start(); } } void MainWindow::onUndoOperation() { Q_ASSERT(operationStack().size() > 0); if (operationStack().size() == 0) return; Log() << xi18nc("@info:status", "Undoing operation: %1", operationStack().operations().last()->description()); operationStack().pop(); // it's possible the undo killed the partition in the clipboard. if there's a partition in the clipboard, try // to find a device for it (OperationStack::findDeviceForPartition() only compares pointers, so an invalid // pointer is not a problem). if no device is found, the pointer must be dangling, so clear the clipboard. if (pmWidget().clipboardPartition() != nullptr && operationStack().findDeviceForPartition(pmWidget().clipboardPartition()) == nullptr) pmWidget().setClipboardPartition(nullptr); pmWidget().updatePartitions(); enableActions(); } void MainWindow::onClearAllOperations() { if (KMessageBox::warningContinueCancel(this, xi18nc("@info", "Do you really want to clear the list of pending operations?"), xi18nc("@title:window", "Clear Pending Operations?"), KGuiItem(xi18nc("@action:button", "Clear Pending Operations"), QStringLiteral("arrow-right")), KStandardGuiItem::cancel(), QStringLiteral("reallyClearPendingOperations")) == KMessageBox::Continue) { Log() << xi18nc("@info:status", "Clearing the list of pending operations."); operationStack().clearOperations(); pmWidget().updatePartitions(); enableActions(); } } void MainWindow::onCreateNewPartitionTable() { Q_ASSERT(pmWidget().selectedDevice()); if (pmWidget().selectedDevice() == nullptr) { qWarning() << "selected device is null."; return; } QPointer dlg = new CreatePartitionTableDialog(this, *pmWidget().selectedDevice()); if (dlg->exec() == QDialog::Accepted) operationStack().push(new CreatePartitionTableOperation(*pmWidget().selectedDevice(), dlg->type())); delete dlg; } void MainWindow::onImportPartitionTable() { Q_ASSERT(pmWidget().selectedDevice()); const QUrl url = QFileDialog::getOpenFileUrl(this, QStringLiteral("Import Partition Table")); if (url.isEmpty()) return; QFile file; if (url.isLocalFile()) { file.setFileName(url.toLocalFile()); if (!file.open(QFile::ReadOnly)) { KMessageBox::error(this, xi18nc("@info", "Could not open input file %1 for import", url.toLocalFile()), xi18nc("@title:window", "Error Importing Partition Table")); return; } } else { QTemporaryFile tempFile; if (!tempFile.open()) { KMessageBox::error(this, xi18nc("@info", "Could not create temporary file when trying to save to %1.", tempFile.fileName()), xi18nc("@title:window", "Error Importing Partition Table")); return; } KIO::FileCopyJob *job = KIO::file_copy(url, QUrl::fromLocalFile(tempFile.fileName())); KJobWidgets::setWindow(job, this); job->exec(); if (job->error()) { KMessageBox::error(this, xi18nc("@info", "Could not open input file %1 for import: %2", url.fileName(), job->errorString()), xi18nc("@title:window", "Error Importing Partition Table")); return; } file.setFileName(tempFile.fileName()); if (!file.open(QFile::ReadOnly)) { KMessageBox::error(this, xi18nc("@info", "Could not open temporary file %1 while trying to import from %2.", tempFile.fileName(), url.fileName()), xi18nc("@title:window", "Error Importing Partition Table")); return; } } Device& device = *pmWidget().selectedDevice(); QString line; quint32 lineNo = 0; bool haveMagic = false; PartitionTable* ptable = nullptr; PartitionTable::TableType tableType = PartitionTable::unknownTableType; while (!(line = QString::fromUtf8(file.readLine())).isEmpty()) { lineNo++; line = line.trimmed(); if (line.isEmpty()) continue; QRegularExpression re(QStringLiteral("(\\d+);(\\d+);(\\d+);(\\w+);(\\w+);(\"\\w*\");(\"[^\"]*\")")); QRegularExpressionMatch rePartition = re.match(line); re.setPattern(QStringLiteral("type:\\s\"(.+)\"")); QRegularExpressionMatch reType = re.match(line); re.setPattern(QStringLiteral("align:\\s\"(cylinder|sector)\"")); QRegularExpressionMatch reAlign = re.match(line); re.setPattern(QStringLiteral("^##|v(\\d+)|##")); QRegularExpressionMatch reMagic = re.match(line); if (!(haveMagic || reMagic.hasMatch())) { KMessageBox::error(this, xi18nc("@info", "The import file %1 does not contain a valid partition table.", url.fileName()), xi18nc("@title:window", "Error While Importing Partition Table")); return; } else haveMagic = true; if (line.startsWith(QStringLiteral("#"))) continue; if (reType.hasMatch()) { if (ptable != nullptr) { KMessageBox::error(this, xi18nc("@info", "Found more than one partition table type in import file (line %1).", lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } tableType = PartitionTable::nameToTableType(reType.captured(1)); if (tableType == PartitionTable::unknownTableType) { KMessageBox::error(this, xi18nc("@info", "Partition table type \"%1\" is unknown (line %2).", reType.captured(1), lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } if (tableType != PartitionTable::msdos && tableType != PartitionTable::gpt) { KMessageBox::error(this, xi18nc("@info", "Partition table type \"%1\" is not supported for import (line %2).", reType.captured(1), lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } ptable = new PartitionTable(tableType, PartitionTable::defaultFirstUsable(device, tableType), PartitionTable::defaultLastUsable(device, tableType)); operationStack().push(new CreatePartitionTableOperation(device, ptable)); } else if (reAlign.hasMatch()) { // currently ignored } else if (rePartition.hasMatch()) { if (ptable == nullptr) { KMessageBox::error(this, xi18nc("@info", "Found partition but no partition table type (line %1).", lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } qint32 num = rePartition.captured(1).toInt(); qint64 firstSector = rePartition.captured(2).toLongLong(); qint64 lastSector = rePartition.captured(3).toLongLong(); QLatin1String fsName = QLatin1String(rePartition.captured(4).toLatin1()); QString roleNames = rePartition.captured(5); QString volumeLabel = rePartition.captured(6).replace(QStringLiteral("\""), QString()); QStringList flags = rePartition.captured(7).replace(QStringLiteral("\""), QString()).split(QStringLiteral(",")); if (firstSector < ptable->firstUsable() || lastSector > ptable->lastUsable()) { KMessageBox::error(this, xi18nc("@info the partition is NOT a device path, just a number", "Partition %1 would be outside the device's boundaries (line %2).", num, lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } if (firstSector >= lastSector) { KMessageBox::error(this, xi18nc("@info", "Partition %1 has end before start sector (line %2).", num, lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } PartitionNode* parent = ptable; Q_ASSERT(parent); PartitionRole role(PartitionRole::None); if (roleNames == QStringLiteral("extended")) role = PartitionRole(PartitionRole::Extended); else if (roleNames == QStringLiteral("logical")) { role = PartitionRole(PartitionRole::Logical); parent = ptable->findPartitionBySector(firstSector, PartitionRole(PartitionRole::Extended)); } else if (roleNames == QStringLiteral("primary")) role = PartitionRole(PartitionRole::Primary); if (role == PartitionRole(PartitionRole::None)) { KMessageBox::error(this, xi18nc("@info the partition is NOT a device path, just a number", "Unrecognized partition role \"%1\" for partition %2 (line %3).", roleNames, num, lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } if (parent == nullptr) { KMessageBox::error(this, xi18nc("@info the partition is NOT a device path, just a number", "No parent partition or partition table found for partition %1 (line %2).", num, lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } if (role.has(PartitionRole::Extended) && !PartitionTable::tableTypeSupportsExtended(tableType)) { KMessageBox::error(this, xi18nc("@info", "The partition table type \"%1\" does not support extended partitions, but one was found (line %2).", PartitionTable::tableTypeToName(tableType), lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } FileSystem* fs = FileSystemFactory::create(FileSystem::typeForName(fsName, { QStringLiteral("C") }), firstSector, lastSector, device.logicalSize()); if (fs == nullptr) { KMessageBox::error(this, xi18nc("@info the partition is NOT a device path, just a number", "Could not create file system \"%1\" for partition %2 (line %3).", fsName, num, lineNo), xi18nc("@title:window", "Error While Importing Partition Table")); return; } if (fs->supportSetLabel() != FileSystem::cmdSupportNone && !volumeLabel.isEmpty()) fs->setLabel(volumeLabel); Partition* p = new Partition(parent, device, role, fs, firstSector, lastSector, QString(), PartitionTable::FlagNone, QString(), false, PartitionTable::FlagNone, Partition::State::New); operationStack().push(new NewOperation(device, p)); } else Log(Log::Level::warning) << xi18nc("@info:status", "Could not parse line %1 from import file. Ignoring it.", lineNo); } if (ptable->type() == PartitionTable::msdos && ptable->isSectorBased(device)) ptable->setType(device, PartitionTable::msdos_sectorbased); } void MainWindow::onExportPartitionTable() { Q_ASSERT(pmWidget().selectedDevice()); Q_ASSERT(pmWidget().selectedDevice()->partitionTable()); const QUrl url = QFileDialog::getSaveFileUrl(); if (url.isEmpty()) return; QTemporaryFile tempFile; if (!tempFile.open()) { KMessageBox::error(this, xi18nc("@info", "Could not create temporary file when trying to save to %1.", url.fileName()), xi18nc("@title:window", "Error Exporting Partition Table")); return; } QTextStream stream(&tempFile); stream << "##|v1|## partition table of " << pmWidget().selectedDevice()->deviceNode() << "\n"; stream << "# on " << QLocale::c().toString(QDateTime::currentDateTime()) << "\n"; stream << *pmWidget().selectedDevice()->partitionTable(); tempFile.close(); KIO::CopyJob* job = KIO::move(QUrl::fromLocalFile(tempFile.fileName()), url, KIO::HideProgressInfo); job->exec(); if (job->error()) job->uiDelegate()->showErrorMessage(); } void MainWindow::onCreateNewVolumeGroup() { QString vgName; QVector pvList; QString type; qint32 raidLevel = 0; qint32 peSize = 4; qint32 chunkSize = 512; // *NOTE*: vgName & pvList will be modified and validated by the dialog QPointer dlg = new CreateVolumeGroupDialog(this, vgName, pvList, type, raidLevel, chunkSize, peSize, operationStack().previewDevices(), operationStack().operations()); if (dlg->exec() == QDialog::Accepted) { if (type == QStringLiteral("LVM")) operationStack().push(new CreateVolumeGroupOperation(vgName, pvList, Device::Type::LVM_Device, peSize)); else if (type == QStringLiteral("RAID")) operationStack().push(new CreateVolumeGroupOperation(vgName, pvList, Device::Type::SoftwareRAID_Device, raidLevel, chunkSize)); } delete dlg; } void MainWindow::onResizeVolumeGroup() { if (pmWidget().selectedDevice()->type() == Device::Type::LVM_Device || pmWidget().selectedDevice()->type() == Device::Type::SoftwareRAID_Device) { VolumeManagerDevice* d = dynamic_cast(pmWidget().selectedDevice()); QVector pvList; // *NOTE*: pvList will be modified and validated by the dialog QPointer dlg = new ResizeVolumeGroupDialog(this, d, pvList, operationStack().previewDevices(), operationStack().operations()); if (dlg->exec() == QDialog::Accepted) operationStack().push(new ResizeVolumeGroupOperation(*d, pvList)); delete dlg; } } void MainWindow::onRemoveVolumeGroup() { Device* tmpDev = pmWidget().selectedDevice(); if (tmpDev->type() == Device::Type::LVM_Device || tmpDev->type() == Device::Type::SoftwareRAID_Device) { operationStack().push(new RemoveVolumeGroupOperation(*(dynamic_cast(tmpDev)))); } } void MainWindow::onDeactivateVolumeGroup() { Device* tmpDev = pmWidget().selectedDevice(); if (tmpDev->type() == Device::Type::LVM_Device || tmpDev->type() == Device::Type::SoftwareRAID_Device) { DeactivateVolumeGroupOperation* deactivate = new DeactivateVolumeGroupOperation( *(dynamic_cast(tmpDev)) ); Report tmpReport(nullptr); if (deactivate->execute(tmpReport)) { deactivate->preview(); actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setEnabled(false); actionCollection()->action(QStringLiteral("deactivateVolumeGroup"))->setEnabled(false); } pmWidget().updatePartitions(); enableActions(); } } void MainWindow::onActivateRAID() { Device* dev = pmWidget().selectedDevice(); if (dev->type() == Device::Type::SoftwareRAID_Device) { ActivateRaidOperation activate(static_cast(dev)); Report report(nullptr); if (activate.execute(report)) activate.preview(); Device *tmp = CoreBackendManager::self()->backend()->scanDevice(dev->deviceNode()); if (tmp) { PartitionTable* ptable = new PartitionTable(*tmp->partitionTable()); dev->setPartitionTable(ptable); } delete tmp; pmWidget().updatePartitions(); enableActions(); } } void MainWindow::onFileSystemSupport() { FileSystemSupportDialog dlg(this); dlg.exec(); } void MainWindow::onShowAboutKPMcore() { KAboutApplicationDialog dlg(aboutKPMcore(), this); dlg.exec(); } void MainWindow::onSettingsChanged() { bool raidChanged = false, backendChanged = false; if (SoftwareRAID::raidConfigurationFilePath() != Config::raidConfigurationFilePath()) { raidChanged = true; loadRaidConfiguration(); } if (CoreBackendManager::self()->backend()->id() != Config::backend()) { backendChanged = true; CoreBackendManager::self()->unload(); // FIXME: if loadBackend() fails to load the configured backend and loads the default // one instead it also sets the default backend in the config; the config dialog will // overwrite that again, however, after we're done here. if (loadBackend()) { deviceScanner().setupConnections(); scanDevices(); FileSystemFactory::init(); } else close(); } if (raidChanged && !backendChanged) scanDevices(); enableActions(); pmWidget().updatePartitions(); PartitionAlignment::setSectorAlignment(Config::sectorAlignment()); emit settingsChanged(); } void MainWindow::onConfigureOptions() { if (ConfigureOptionsDialog::showDialog(QStringLiteral("Settings"))) return; QPointer dlg = new ConfigureOptionsDialog(this, operationStack(), QStringLiteral("Settings")); // FIXME: we'd normally use settingsChanged(), according to the kde api docs. however, this // is emitted each time the user changes any of our own settings (backend, default file system), without // applying or clicking ok. so the below is the workaround for that. connect(dlg->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &MainWindow::onSettingsChanged); connect(dlg->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &MainWindow::onSettingsChanged); dlg->show(); } void MainWindow::onSmartStatusDevice() { Q_ASSERT(pmWidget().selectedDevice()); if (pmWidget().selectedDevice()) { QPointer dlg = new SmartDialog(this, *pmWidget().selectedDevice()); dlg->exec(); delete dlg; } } void MainWindow::onPropertiesDevice(const QString&) { Q_ASSERT(pmWidget().selectedDevice()); if (pmWidget().selectedDevice()) { Device& d = *pmWidget().selectedDevice(); QPointer dlg = new DevicePropsDialog(this, d); if (dlg->exec() == QDialog::Accepted) { if (d.partitionTable()->type() == PartitionTable::msdos && dlg->sectorBasedAlignment()) d.partitionTable()->setType(d, PartitionTable::msdos_sectorbased); else if (d.partitionTable()->type() == PartitionTable::msdos_sectorbased && dlg->cylinderBasedAlignment()) d.partitionTable()->setType(d, PartitionTable::msdos); on_m_OperationStack_devicesChanged(); pmWidget().updatePartitions(); } delete dlg; } } static KLocalizedString checkSupportInNode(const PartitionNode* parent) { if (parent == nullptr) return KLocalizedString(); KLocalizedString rval; for (const auto &node : parent->children()) { const Partition* p = dynamic_cast(node); if (p == nullptr) continue; if (node->children().size() > 0 && !rval.isEmpty()) rval = kxi18n("%1%2").subs(rval).subs(checkSupportInNode(node)); else rval = checkSupportInNode(node); if ((!p->fileSystem().supportToolFound() && !p->fileSystem().supportToolName().name.isEmpty()) && !rval.isEmpty()) rval = kxi18n("%1%2").subs(rval).subs(kxi18n("" "%1" "%2" "%3" "%4" "") .subs(p->deviceNode()) .subs(p->fileSystem().name()) .subs(p->fileSystem().supportToolName().name) .subs(p->fileSystem().supportToolName().url.toString())); else if (!p->fileSystem().supportToolFound() && !p->fileSystem().supportToolName().name.isEmpty()) rval =kxi18n("" "%1" "%2" "%3" "%4" "") .subs(p->deviceNode()) .subs(p->fileSystem().name()) .subs(p->fileSystem().supportToolName().name) .subs(p->fileSystem().supportToolName().url.toString()); } return rval; } void MainWindow::checkFileSystemSupport() { KLocalizedString supportList, supportInNode; bool missingSupportTools = false; const auto previewDevices = operationStack().previewDevices(); for (auto const &d : previewDevices ) { supportInNode = checkSupportInNode(d->partitionTable()); if (!supportInNode.isEmpty() && !supportList.isEmpty()) { missingSupportTools = true; supportList = kxi18n("%1%2").subs(supportList).subs(supportInNode); } else if (!supportInNode.isEmpty()) { missingSupportTools = true; supportList = supportInNode; } } if (missingSupportTools) KMessageBox::information(this, xi18nc("@info", "No support tools were found for file systems currently present on hard disks in this computer:" "" "" "" "" "" "" "" "%1" "
PartitionFile SystemSupport ToolsURL
" "As long as the support tools for these file systems are not installed you will not be able to modify them." "You should find packages with these support tools in your distribution's package manager.", supportList), xi18nc("@title:window", "Missing File System Support Packages"), QStringLiteral("showInformationOnMissingFileSystemSupport"), KMessageBox::Notify | KMessageBox::AllowLink); } diff --git a/src/gui/resizedialog.cpp b/src/gui/resizedialog.cpp index 6e45b6e..3921e11 100644 --- a/src/gui/resizedialog.cpp +++ b/src/gui/resizedialog.cpp @@ -1,166 +1,166 @@ /************************************************************************* * 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/resizedialog.h" #include "gui/sizedialogwidget.h" #include "gui/sizedetailswidget.h" #include #include #include #include #include #include #include #include #include #include /** Creates a new ResizeDialog @param parent pointer to the parent widget @param d the Device the Partition to resize is on @param p the Partition to resize @param minFirst the first free sector before the Partition to resize @param maxLast the last free sector free after the Partition to resize */ ResizeDialog::ResizeDialog(QWidget* parent, Device& d, Partition& p, qint64 minFirst, qint64 maxLast) : SizeDialogBase(parent, d, p, minFirst, maxLast), m_OriginalFirstSector(p.firstSector()), m_OriginalLastSector(p.lastSector()), m_ResizedFirstSector(p.firstSector()), m_ResizedLastSector(p.lastSector()) { setWindowTitle(xi18nc("@title:window", "Resize/move partition: %1", partition().deviceNode())); dialogWidget().hideRole(); dialogWidget().hideFileSystem(); dialogWidget().hideLabel(); dialogWidget().textLVName().hide(); dialogWidget().lvName().hide(); setupDialog(); setupConstraints(); setupConnections(); KConfigGroup kcg(KSharedConfig::openConfig(), "resizeDialog"); restoreGeometry(kcg.readEntry("Geometry", QByteArray())); } /** Destroys a ResizeDialog */ ResizeDialog::~ResizeDialog() { KConfigGroup kcg(KSharedConfig::openConfig(), "resizeDialog"); kcg.writeEntry("Geometry", saveGeometry()); } void ResizeDialog::rollback() { partition().setFirstSector(originalFirstSector()); partition().fileSystem().setFirstSector(originalFirstSector()); partition().setLastSector(originalLastSector()); partition().fileSystem().setLastSector(originalLastSector()); if (partition().roles().has(PartitionRole::Extended)) { device().partitionTable()->removeUnallocated(&partition()); device().partitionTable()->insertUnallocated(device(), &partition(), partition().firstSector()); } } void ResizeDialog::accept() { if (partition().roles().has(PartitionRole::Luks)) { FS::luks2* luksFs = dynamic_cast(&partition().fileSystem()); if (luksFs) { if (luksFs->keyLocation() == FS::luks::KeyLocation::keyring) { bool validPassphrase = false; QString errorMessage; QString passphrase; - while(!validPassphrase) { + while (!validPassphrase) { KPasswordDialog dlg( this ); dlg.setPrompt(i18nc("%2 is either empty or says Invalid passphrase.", "%2Enter passphrase for %1:", partition().deviceNode(), errorMessage)); - if( !dlg.exec() ) { + if (!dlg.exec()) { reject(); return; } passphrase = dlg.password(); validPassphrase = luksFs->testPassphrase(partition().deviceNode(), passphrase); if(!validPassphrase) errorMessage = i18nc("Part of %2Enter passphrase for %1:", "Invalid passphrase. "); } luksFs->setPassphrase(passphrase); } } } setResizedFirstSector(partition().firstSector()); setResizedLastSector(partition().lastSector()); rollback(); QDialog::accept(); } void ResizeDialog::reject() { rollback(); QDialog::reject(); } void ResizeDialog::setupDialog() { SizeDialogBase::setupDialog(); if (device().type() == Device::Type::LVM_Device) { dialogWidget().hideBeforeAndAfter(); detailsWidget().checkAlign().setChecked(false); detailsWidget().checkAlign().setEnabled(false); detailsButton->hide(); } okButton->setEnabled(false); } void ResizeDialog::setDirty() { okButton->setEnabled(isModified()); } /** @return true if the user modified anything */ bool ResizeDialog::isModified() const { return partition().firstSector() != originalFirstSector() || partition().lastSector() != originalLastSector(); } bool ResizeDialog::canGrow() const { return ResizeOperation::canGrow(&partition()); } bool ResizeDialog::canShrink() const { return ResizeOperation::canShrink(&partition()); } bool ResizeDialog::canMove() const { return (device().type() == Device::Type::LVM_Device) ? false : ResizeOperation::canMove(&partition()); } diff --git a/src/gui/smartdialogwidgetbase.ui b/src/gui/smartdialogwidgetbase.ui index 64a1ca5..2f09795 100644 --- a/src/gui/smartdialogwidgetbase.ui +++ b/src/gui/smartdialogwidgetbase.ui @@ -1,438 +1,431 @@ SmartDialogWidgetBase 0 0 - 649 - 483 + 750 + 550 2 0 SMART status: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 16 16777215 - + 2 0 Model: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 - + 2 0 Serial number: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 - + 2 0 Firmware revision: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 - + 2 0 Temperature: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 - + 2 0 Bad sectors: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 - + 2 0 Powered on for: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 - + 2 0 Power cycles: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 Qt::Vertical QSizePolicy::Fixed 641 17 - + true false true true Id Attribute Failure Type Update Type Worst Current Threshold Raw Assessment Value Qt::Vertical QSizePolicy::Fixed 638 17 - + Qt::Horizontal - + Qt::Horizontal - - - - Qt::Horizontal - - - - + 2 0 Overall assessment: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 - + 2 0 Self tests: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 3 0 diff --git a/src/gui/volumegroupdialog.cpp b/src/gui/volumegroupdialog.cpp index 50b61ed..9232823 100644 --- a/src/gui/volumegroupdialog.cpp +++ b/src/gui/volumegroupdialog.cpp @@ -1,206 +1,206 @@ /************************************************************************* * Copyright (C) 2016 by Chantara Tith * * 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/volumegroupdialog.h" #include "gui/volumegroupwidget.h" #include #include #include #include #include #include #include #include #include #include #include /** Creates a new VolumeGroupDialog @param parent pointer to the parent widget @param vgName Volume Group name @param pvList List of LVM Physical Volumes used to create Volume Group */ VolumeGroupDialog::VolumeGroupDialog(QWidget* parent, QString& vgName, QVector& pvList) : QDialog(parent), m_DialogWidget(new VolumeGroupWidget(this)), m_TargetName(vgName), m_TargetPVList(pvList), m_IsValidSize(false), m_IsValidName(true), m_TotalSize(0), m_TotalUsedSize(0), m_ExtentSize(0) { mainLayout = new QVBoxLayout(this); setLayout(mainLayout); mainLayout->addWidget(&dialogWidget()); dialogButtonBox = new QDialogButtonBox; okButton = dialogButtonBox->addButton(QDialogButtonBox::Ok); cancelButton = dialogButtonBox->addButton(QDialogButtonBox::Cancel); mainLayout->addWidget(dialogButtonBox); cancelButton->setFocus(); cancelButton->setDefault(true); setupDialog(); setupConstraints(); setupConnections(); } /** Destroys a VolumeGroupDialog */ VolumeGroupDialog::~VolumeGroupDialog() { KConfigGroup kcg(KSharedConfig::openConfig(), "createVolumeGroupDialog"); kcg.writeEntry("Geometry", saveGeometry()); } void VolumeGroupDialog::setupDialog() { dialogWidget().volumeType().addItems({ QStringLiteral("LVM"), QStringLiteral("RAID") }); dialogWidget().volumeType().setCurrentIndex(0); dialogWidget().raidLevel().addItems({ QStringLiteral("0"), QStringLiteral("1"), QStringLiteral("4"), QStringLiteral("5"), QStringLiteral("6"), QStringLiteral("10") }); updateNameValidator(); updateComponents(); setMinimumSize(dialogWidget().size()); resize(dialogWidget().size()); } void VolumeGroupDialog::setupConnections() { connect(dialogButtonBox, &QDialogButtonBox::accepted, this, &VolumeGroupDialog::accept); connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &VolumeGroupDialog::reject); connect(&dialogWidget().volumeType(), qOverload(&QComboBox::currentIndexChanged), this, &VolumeGroupDialog::onVolumeTypeChanged); connect(&dialogWidget().listPV().listPhysicalVolumes(), &QListWidget::itemChanged, this, [=] ( QListWidgetItem*) { updateSizeInfos(); }); } void VolumeGroupDialog::setupConstraints() { updateSizeInfos(); updateOkButtonStatus(); } void VolumeGroupDialog::updateOkButtonStatus() { bool enable = isValidSize(); if (dialogWidget().vgName().text().isEmpty() || !isValidName()) { enable = false; } if (dialogWidget().spinPESize().value() <= 0) { enable = false; } okButton->setEnabled(enable); } void VolumeGroupDialog::updateSectorInfos() { qint32 totalSectors = 0; if (dialogWidget().volumeType().currentText() == QStringLiteral("LVM")) { - // we can't use LvmDevice mothod here because pv that is not in any VG will return 0 + // we can't use LvmDevice method here because pv that is not in any VG will return 0 m_ExtentSize = dialogWidget().spinPESize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB); if (m_ExtentSize > 0) totalSectors = m_TotalSize / m_ExtentSize; } else if (dialogWidget().volumeType().currentText() == QStringLiteral("RAID")) { m_ExtentSize = dialogWidget().chunkSize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::KiB); if (m_ExtentSize > 0) totalSectors = m_TotalSize / m_ExtentSize; } dialogWidget().totalSectors().setText(QString::number(totalSectors)); } void VolumeGroupDialog::updateSizeInfos() { QString type = dialogWidget().volumeType().currentText(); const QVector checkedPartitions = dialogWidget().listPV().checkedItems(); m_TotalSize = 0; for (const auto &p : checkedPartitions) m_TotalSize += p->capacity() - p->capacity() % (type == QStringLiteral("LVM") ? (dialogWidget().spinPESize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB)) : (dialogWidget().chunkSize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::KiB))); // subtract space which is too small to hold PE dialogWidget().totalSize().setText(Capacity::formatByteSize(m_TotalSize)); //Probably a bad design for updating state here; the state should be changed inside the update button function. m_IsValidSize = m_TotalSize >= m_TotalUsedSize; updateSectorInfos(); updateOkButtonStatus(); } void VolumeGroupDialog::updatePartitionList() { } void VolumeGroupDialog::updateNameValidator() { if (dialogWidget().volumeType().currentText() == QStringLiteral("LVM")) { /* LVM Volume group name can consist of: letters numbers _ . - + * It cannot start with underscore _ and must not be equal to . or .. or any entry in /dev/ * QLineEdit accepts QValidator::Intermediate, so we just disable . at the beginning */ QRegularExpression re(QStringLiteral(R"(^(?!_|\.)[\w\-.+]+)")); QRegularExpressionValidator *validator = new QRegularExpressionValidator(re, this); dialogWidget().vgName().setValidator(validator); dialogWidget().vgName().setText(targetName()); } else if (dialogWidget().volumeType().currentText() == QStringLiteral("RAID")) { // TODO: See how Software RAID names should be validated. } } void VolumeGroupDialog::onPartitionListChanged() { } void VolumeGroupDialog::onVolumeTypeChanged(int index) { Q_UNUSED(index) updateNameValidator(); updatePartitionList(); updateComponents(); } void VolumeGroupDialog::updateComponents() { dialogWidget().spinPESize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("LVM")); dialogWidget().textTotalPESize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("LVM")); dialogWidget().raidLevel().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID")); dialogWidget().textRaidLevel().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID")); dialogWidget().chunkSize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID")); dialogWidget().textChunkSize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID")); } diff --git a/src/main.cpp b/src/main.cpp index fe9c847..57d0441 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,87 +1,88 @@ /************************************************************************* * Copyright (C) 2008,2011 by Volker Lanz * * Copyright (C) 2014-2018 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/mainwindow.h" #include #include #include #include "util/guihelpers.h" #include #include #include #include #include #include #include #include int Q_DECL_IMPORT main(int argc, char* argv[]) { QApplication app(argc, argv); + app.setWindowIcon(QIcon::fromTheme(QStringLiteral("partitionmanager"))); KLocalizedString::setApplicationDomain("partitionmanager"); KAboutData aboutData ( QStringLiteral("partitionmanager"), xi18nc("@title", "KDE Partition Manager"), QStringLiteral(VERSION), xi18nc("@title", "Manage your disks, partitions and file systems"), KAboutLicense::GPL_V3, xi18nc("@info:credit", "© 2008-2013 Volker Lanz\n© 2012-2018 Andrius Štikonas")); aboutData.setOrganizationDomain(QByteArray("kde.org")); aboutData.setProductName(QByteArray("partitionmanager")); aboutData.addAuthor(xi18nc("@info:credit", "Volker Lanz"), xi18nc("@info:credit", "Former maintainer")); aboutData.addAuthor(xi18nc("@info:credit", "Andrius Štikonas"), xi18nc("@info:credit", "Maintainer"), QStringLiteral("andrius@stikonas.eu")); aboutData.addCredit(xi18nc("@info:credit", "Teo Mrnjavac"), i18nc("@info:credit", "Former Calamares maintainer"), QStringLiteral("teo@kde.org")); aboutData.addCredit(xi18nc("@info:credit", "Chantara Tith"), i18nc("@info:credit", "LVM support"), QStringLiteral("tith.chantara@gmail.com")); aboutData.addCredit(xi18nc("@info:credit", "Pali Rohár"), i18nc("@info:credit", "UDF support"), QStringLiteral("pali.rohar@gmail.com")); aboutData.setHomepage(QStringLiteral("https://www.kde.org/applications/system/kdepartitionmanager")); aboutData.addCredit(i18n("Hugo Pereira Da Costa"), xi18nc("@info:credit", "Partition Widget Design"), QStringLiteral("hugo@oxygen-icons.org")); KAboutData::setApplicationData(aboutData); app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); KCrash::initialize(); QCommandLineParser parser; aboutData.setupCommandLine(&parser); // FIXME parser.addPositionalArgument(QStringLiteral("device"), xi18nc("@info:shell", "Device(s) to manage"), QStringLiteral("[device...]")); parser.process(app); aboutData.processCommandLine(&parser); KDBusService service(KDBusService::Unique); registerMetaTypes(); Config::instance(QStringLiteral("partitionmanagerrc")); if (!loadBackend()) return 0; loadRaidConfiguration(); MainWindow* mainWindow = new MainWindow(); Q_UNUSED(mainWindow) return app.exec(); } diff --git a/src/org.kde.partitionmanager.appdata.xml b/src/org.kde.partitionmanager.appdata.xml index d7c041e..5d621cb 100644 --- a/src/org.kde.partitionmanager.appdata.xml +++ b/src/org.kde.partitionmanager.appdata.xml @@ -1,244 +1,244 @@ org.kde.partitionmanager.desktop CC0-1.0 GPL-3.0+ KDE Partition Manager مدير كدي للأقسام - Xestor KDE de particiones + Xestor de particiones de KDE KDE‑ov menadžer particija Gestor de particions del KDE Gestor de particions del KDE Správce diskových oddílů pro KDE KDE Partitionshåndtering KDE-Partitionsverwaltung Διαχειριστής κατατμήσεων του KDE KDE Partition Manager Gestor de particiones de KDE KDE partitsioonide haldur KDE:n osionhallinta Gestionnaire de partitions de KDE Xestor de particións de KDE KDE partíciókezelő KDE Partition Manager Gestore delle partizioni di KDE KDE 파티션 관리자 KDE Skaidinių tvarkyklė KDE Partitiebeheerder KDE ਪਾਰਟੀਸ਼ਨ ਮੈਨੇਜਰ Zarządzanie partycjami KDE Gestor de Partições do KDE Gerenciador de Partições do KDE Gestionarul de partiții KDE KDE Správca partícií Upravljalnik razdelkov za KDE КДЕ‑ов менаџер партиција KDE‑ov menadžer particija КДЕ‑ов менаџер партиција KDE‑ov menadžer particija KDE:s partitionshanterare KDE Disk Bölüm Yöneticisi Редактор розділів для KDE xxKDE Partition Managerxx KDE 分区管理器 KDE 磁碟分割區管理員 Partition Editor محرّر أقسام Editor de particiones Uređivač particija Editor de particions Editor de particions Editor diskových oddílů Partitioneringsprogram Partition-Editor Διαχειριστής κατατμήσεων Partition Editor Editor de particiones Partitsiooniredaktor Osionhallinta Éditeur de partitions Editor de particións Partíciószerkesztő Pengedit Partisi Editor delle partizioni 파티션 편집기 Skaidinių tvarkyklė Partitiebewerker ਪਾਰਟੀਸ਼ਨ ਮੈਨੇਜਰ Zarządzanie partycjami Editor de Partições Editor de Partições Redactor de partiții Editor partícií Urejevalnik razdelkov Уређивач партиција Uređivač particija Уређивач партиција Uređivač particija Partitionseditor Disk Bölümü Düzenleyici Редактор розділів диска xxPartition Editorxx 分区编辑器 磁碟分割區編輯器

KDE Partition Manager is a utility program to help you manage the disk devices, partitions and file systems on your computer. It allows you to easily create, copy, move, delete, resize without losing data, backup and restore partitions.

«مدير كدي للأقسام» هو أداة تساعدك على إدارة أجهزة الأقراص، والأقسام وأنظمة الملفّات في حاسوبك. ويتيح لك الإنشاء، والنّسخ، والنّقل، والحذف، والتّحجيم دون فقدات البيانات، والنّسخ الاحتياطيّ واسترجاع الأقسام بسهولة.

-

El xestor KDE de particiones ye una utilidá p'ayudate a xestionar los discos, particiones y sistemes de ficheros nel to ordenador. Permítete crear, copiar, mover, desaniciar, redimensionar ensin perder nada, respaldar y restaurar particiones de mou cenciellu.

+

El xestor de particiones de KDE ye una utilidá p'ayudate a xestionar los preseos d'almacenamientu, particiones y sistemes de ficheros del ordenador. Permítete crear, copiar, mover, desaniciar, redimensionar ensin perder datos, facer copies de seguranza y restaurar particiones fácilmente

El gestor de particions del KDE és un programa d'utilitats que us ajuda a gestionar els dispositius de disc, les particions i els sistemes de fitxers de l'ordinador. Us permet crear, moure, eliminar, redimensionar sense perdre dades, fer còpies de seguretat i restaurar particions fàcilment.

El gestor de particions del KDE és un programa d'utilitats que vos ajuda a gestionar els dispositius de disc, les particions i els sistemes de fitxers de l'ordinador. Vos permet crear, moure, eliminar, redimensionar sense perdre dades, fer còpies de seguretat i restaurar particions fàcilment.

KDE Partition Manager er et værktøj til at hjælpe dig med at håndtere dine diskenheder og filsystemerne på din computer. Den lader dig nemt oprette, kopiere, flytte, slette, ændre størrelse uden at miste data, tage backup og gendanne partitioner.

KDE-Partitionsverwaltung ist ein Dienstprogramm zur Verwaltung der Festplattengeräte, Partitionen und Dateisystemen auf Ihrem Rechner. Damit können Sie Partitionen einfach erstellen, kopieren, verschieben, deren Größe ohne Datenverlust verändern und Partitionen sichern und wieder herstellen.

Ο διαχειριστής κατατμήσεων του KDE είναι ένα εργαλείο που σας βοηθά να διαχειριστείτε τους δίσκους, τις κατατμήσεις και τα συστήματα αρχείων του υπολογιστή σας. Σας επιτρέπει να δημιουργείτε,αντιγράφετε, μετακινείτε, διαγράφετε, να αλλάζετε το μέγεθος χωρίς να χάνετε δεδομένα, να κρατάτε αντίγραφα ασφαλείας και να επαναφέρετε κατατμήσεις εύκολα.

KDE Partition Manager is a utility program to help you manage the disk devices, partitions and file systems on your computer. It allows you to easily create, copy, move, delete, resize without losing data, backup and restore partitions.

El gestor de particiones de KDE es una utilidad que le ayuda a gestionar los dispositivos de disco duro, las particiones y el sistema de archivos de su equipo. Le permite crear, copiar, mover, borrar, cambiar el tamaño sin perder datos, hacer copia de seguridad y restaurar particiones.

KDE partitsioonide haldur on tööriist, mis aitab hallata kettaseadmeid, partitsioone ja failisüsteeme sinu arvutis. See võimaldab vähese vaevaga partitsioone luua, kopeerida, liigutada, kustutada, muuta suurust andmeid kaotamata, varundada ja taastada.

KDE:n osionhallinta on apuohjelma, joka auttaa hallitsemaan tietokoneen levyjä, osioita ja tiedostojärjestelmiä. Sillä voi luoda, kopioida, siirtää, poistaa, muuttaa kokoa menettämättä tietoja, varmuuskopioida ja palauttaa osioita.

Le gestionnaire de partitions de KDE est un utilitaire qui vous aide à gérer les disques, partitions et systèmes de fichiers de votre ordinateur. Il vous permet de créer, copier, déplacer, supprimer, redimensionner sans perte, sauvegarder et rétablir des partitions facilement.

O xestor de particións de KDE é unha ferramenta que lle permite xestionar os seus dispositivos de almacenamento, as particións e os sistemas de ficheiros do seu computador. A ferramenta permite crear, copiar, mover, eliminar, cambiar de tamaño sen perder datos, facer copias de seguranza e restaurar particións, todo de maneira sinxela.

A KDE partíciókezelő egy segédprogram, mely segít Önnek lemezek, partíciók és fájlrendszerek kezelésében. Lehetővé teszi partíciók létrehozását, másolását, mozgatását, törlését, adatvesztés nélküli átméretezését, biztonsági mentését és visszaállítását.

KDE Partition Manager adalah sebuah program utilitas untuk membantu Anda mengelola perangkat disk, partisi dan sistem file di komputer Anda. Hal ini memungkinkan Anda untuk mudah menciptakan, menyalin, memindah, menghapus, mengubah-ukuran tanpa kehilangan data, mencadang dan memulihkan partisi.

Il gestore delle partizioni di KDE è un programma che ti aiuta a gestire i dischi, le partizioni e i filesystem sul tuo computer. Ti consente di creare, copiare, spostare, eliminare, ridimensionare senza perdere dati, effettuare copie di sicurezza e ripristinare partizioni con grande semplicità.

KDE 파티션 관리자는 컴퓨터의 디스크 장치, 파티션, 파일 시스템을 관리하는 도구입니다. 파티션 작업, 무손실 크기 조정, 백업과 복원이 가능합니다.

KDE Skaidinių tvarkyklė yra programa padedanti tvarkyti jūsų kompiuterio diskų įrenginius, skaidinius ir failų sistemas. Ji leidžia lengvai kurti, kopijuoti, perkelti, trinti ir keisti dydį neprarandant duomenų, kurti atsargines skaidinių kopijas.

KDE Partitiebeheerder is een hulpprogramma om u helpen bij het beheer van de schijven, partities en bestandssystemen op uw computer. Het stelt u in staat gemakkelijk partities te maken, te kopiëren, te verplaatsen, te verwijderen, hun grootte te wijzigen zonder verlies van gegevens en hiervan een reservekopie te maken of hier vanaf te herstellen.

Zarządzanie partycjami KDE jest programem użytkowym mającym na celu pomoc przy zarządzaniu urządzeniami dyskowymi, partycjami i systemami plików na twoim komputerze. Umożliwia łatwe tworzenie, kopiowanie, przenoszenie, usuwanie i zamianę rozmiaru bez utraty danych, a także tworzenie i przywracanie kopii zapasowych partycji.

O Gestor de Partições do KDE é um utilitário que o ajuda a gerir os dispositivos dos discos, as suas partições e sistemas de ficheiros no seu computador. Permite-lhe facilmente criar, copiar, mover, apagar, dimensionar sem perder dados, salvaguardar e repor partições.

O Gerenciador de Partições do KDE é um utilitário que o ajuda a gerenciar os dispositivos de disco, suas partições e sistemas de arquivos no seu computador. Permite-lhe facilmente criar, copiar, mover, excluir, redimensionar sem perder dados, criar backup e restaurar partições.

KDE správca partícií je nástroj, ktorý vám má pomôcť spravovať diskové zariadenia, partície a súborové systémy na vašom počítači. Umožňuje vám jednoducho vytvoriť, kopírovať, presúvať, mazať a meniť veľkosť bez straty dám, zálohovať a obnovovať partície.

Upravljalnik razdelkov za KDE je pripomoček, ki vam omogoča upravljanje z diski, razdelki in datotečnimi sistemi na vašem računalniku. Z njim lahko enostavno ustvarite, kopirate, premaknete, izbrišete, varnostno kopirate in obnovite ter spreminjate velikost razdelkov brez izgube podatkov.

КДЕ‑ов менаџер партиција је алатка за управљање дисковима, партицијама и фајл системима на рачунару. Омогућава лако стварање, копирање, премештање и брисање партиција, промену величине без губитка података, прављење и враћање резерва партиција.

KDE‑ov menadžer particija je alatka za upravljanje diskovima, particijama i fajl sistemima na računaru. Omogućava lako stvaranje, kopiranje, premeštanje i brisanje particija, promenu veličine bez gubitka podataka, pravljenje i vraćanje rezerva particija.

КДЕ‑ов менаџер партиција је алатка за управљање дисковима, партицијама и фајл системима на рачунару. Омогућава лако стварање, копирање, премештање и брисање партиција, промену величине без губитка података, прављење и враћање резерва партиција.

KDE‑ov menadžer particija je alatka za upravljanje diskovima, particijama i fajl sistemima na računaru. Omogućava lako stvaranje, kopiranje, premeštanje i brisanje particija, promenu veličine bez gubitka podataka, pravljenje i vraćanje rezerva particija.

KDE Partition Manager är ett verktyg för att hjälpa till att hantera diskenheter, partitioner och filsystem på datorn. Det låter dig enkelt skapa, kopiera, flytta, ta bort, ändra storlek utan dataförlust, säkerhetskopiera och återställa partitioner.

KDE Disk Bölümü Düzenleyici; bilgisayarınızdaki disk aygıtlarını, bölümlerinizi ve dosya sistemlerinizi yönetmenize yardımcı olan bir programdır. Kolaylıkla disk bölümü oluşturmanızı, kopyalamanızı, taşımanızı, silmenizi, veri kaybetmeden yeniden boyutlandırmanızı, yedeklemenizi ve yedekten geri yüklemenizi sağlar.

Редактор розділів KDE — допоміжна програма, яку призначено для полегшення керування дисковими пристроями, розділами та файловими системами на комп’ютері. За її допомогою ви зможете без проблем створювати, копіювати, пересувати, вилучати та змінювати розміри розділів без втрати даних, створювати резервні копії розділів та відновлювати дані з цих резервних копій.

xxKDE Partition Manager is a utility program to help you manage the disk devices, partitions and file systems on your computer. It allows you to easily create, copy, move, delete, resize without losing data, backup and restore partitions.xx

KDE 分区管理器是一个帮助您管理就计算机上的磁盘设备,分区,文件系统的工具程序。它可以帮助您简单地创建,复制,移动,删除,无损调整大小,备份和恢复分区。

KDE 磁碟分割區管理員是一個可以協助您管理您電腦上的磁碟裝置、分割區以及檔案系統的工具。它讓您可以很容易地建立、複製、移動、刪除、不遺失資料的調整大小、備份與恢復分割區。

Features:

الميزات:

-

Carauterístiques

+

Carauterístiques:

Svojstva:

Característiques:

Característiques:

Vlastnosti:

Funktioner:

Funktionen:

Χαρακτηριστικά:

Features:

Funciones:

Omadused:

Ominaisuudet:

Fonctionnalités :

Funcionalidades:

Szolgáltatások:

Fitur:

Funzionalità:

기능:

Ypatybės:

Mogelijkheden:

ਲੱਛਣ:

Możliwości:

Funcionalidades:

Funcionalidades:

Caracteristici:

Funkcie:

Zmožnosti:

Могућности:

Mogućnosti:

Могућности:

Mogućnosti:

Funktioner:

Özellikler:

Можливості:

xxFeatures:xx

功能:

功能:

  • Supports a large number of file systems, including ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS and more
  • يدعم عددًا كبيرًا من أنظمة الملفّات، منها ext2/3/4، وbtrfs، وreiserfs، وNTFS، وFAT16/32، وJFS، وXFS وغيرها
  • -
  • Sofita un númberu grande de sistemes de ficheros incluyendo ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS y más
  • +
  • Sofita un númberu grande de sistemes de ficheros, incluyendo ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS y más
  • Accepta un gran nombre de sistemes de fitxers, incloent-hi ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS i més
  • Accepta un gran nombre de sistemes de fitxers, incloent-hi ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS i més
  • Understøtter et større antal filsystemer, derunder ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS og andre
  • Unterstützt eine große Zahl von Dateisystemen, einschließlich ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS und weitere
  • Υποστηρίζει μαι σειρά συστημάτων αρχείων, συμπεριλαμβανομένων των ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS και άλλων
  • Supports a large number of file systems, including Ext2/3/4, Btrfs, ReiserFS, NTFS, FAT16/32, JFS, XFS and more
  • Permite un gran número de sistemas de archivos, como ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS y XFS, entre otros
  • Paljude failisüsteemide toetus, sealhulgas ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS ja veel paljud
  • Tukee monia tiedostojärjestelmiä kuten ext2/3/4, Btrfs, ReiserFS, NTFS, FAT16/32, JFS, XFS ja muita
  • Prend en charge un grand nombre de systèmes de fichiers, notamment ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS et d'autres
  • Compatíbel cun gran número de sistemas de ficheiros, entre eles ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS, e máis.
  • Számos fájlrendszer támogatása, többek között ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS és továbbiak
  • Mendukung sejumlah besar sistem file , termasuk ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS dan lebih banyak lagi
  • Supporta un vasto numero di filesystem, tra cui ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS e altri
  • EXT2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS 등 파일 시스템 지원
  • Palaiko daug failų sistemų, tarp jų ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS ir kitos
  • Ondersteunt een groot aantal bestandssystemen, inclusief ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS en meer
  • Obsługa wielu systemów plików, uwzględniając przy tym ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS i więcej
  • Suporta um grande conjunto de sistemas de ficheiros, incluindo o ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS entre outros
  • Suporte a um grande conjunto de sistemas de arquivos, incluindo o ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS, entre outros
  • Podporuje veľký počet súborových systémov, vrátane ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS a viac
  • Podpira številne datotečne sisteme vključno z ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS in XFS
  • Подржава велики број фајл система, укључујући екст‑2/3/4, бтрфс, рајзер, НТФС, ФАТ‑16/32, ЈФС, ИксФС, и друге.
  • Podržava veliki broj fajl sistema, uključujući ext2/3/4, btrfs, reiser, NTFS, FAT16/32, JFS, XFS, i druge.
  • Подржава велики број фајл система, укључујући екст‑2/3/4, бтрфс, рајзер, НТФС, ФАТ‑16/32, ЈФС, ИксФС, и друге.
  • Podržava veliki broj fajl sistema, uključujući ext2/3/4, btrfs, reiser, NTFS, FAT16/32, JFS, XFS, i druge.
  • Stöder ett stort antal filsystem, inklusive ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS med flera
  • Ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS ve daha birçok sayıda dosya sistemi destekler
  • Підтримка широкого набору файлових систем, зокрема ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS тощо.
  • xxSupports a large number of file systems, including ext2/3/4, btrfs, reiserfs, NTFS, FAT16/32, JFS, XFS and morexx
  • 支持许多文件系统,包括 ext2/3/4,btrfs,reiserfs,NTFS,FAT16/32,JFS,XFS 和更多
  • 支援大量的檔案系統,包含了 ext2/3/4、btrfs、reiserfs、NTFS、FAT16/32、JFS、XFS 以及更多
  • Makes use of already available external programs to get its job done
  • يستخدم البرامج الخارجيّة المتوفّرة لإنهاء عمله
  • -
  • Fai usu de programes esternos yá disponibles pa facer el so trabayu
  • +
  • Fai usu de programes esternos que yá tean disponibles pa facer el trabayu
  • Fa ús de programes externs ja disponibles per fer la seva feina
  • Fa ús de programes externs ja disponibles per fer la seua faena
  • Gør brug af allerede tilgængelige eksterne programmer til at udføre arbejdet
  • Verwendet bereits vorhandene externe Programme, um die Aufgaben zu erfüllen
  • Χρησιμοποιεί τα ήδη διαθέσιμα εξωτερικά προγράμματα για να κάνει τη δουλειά του
  • Makes use of already available external programs to get its job done
  • Utiliza varios programas externos que deben estar disponibles para realizar el trabajo
  • Saadaolevate väliste programmide kasutamine vajalike tegevuste sooritamiseks
  • Hoitaa hommansa hyödyntäen valmiita ulkoisia ohjelmia
  • Utilise des programmes externes existants pour faire le travail
  • Usa programas externos para realizar as tarefas.
  • A meglévő külső programokat használja a feladatok elvégzésére
  • Membuat penggunaan program eksternal yang sudah ada untuk menyelesaikan pekerjaannya
  • Utilizza programmi esterni già disponibili per fare il suo lavoro
  • 외부 프로그램을 사용한 작업 관리
  • Užduotims atlikti naudoja išorinius įrankius
  • Maakt gebruik van al beschikbare externe programma's om deze taken uit te voeren
  • Wykorzystywanie już dostępnych programów zewnętrznych do wykonywania swojej pracy
  • Tira partido dos programas externos já existentes para terminar a sua tarefa
  • Utiliza os programas externos já existentes para terminar a sua tarefa
  • Používa už existujúce dostupné externé programy na vykonanie svojej práce
  • Za izvedbo poslov uporablja že obstoječe zunanje programe
  • Користи разне већ постојеће спољашње програма да обави посао.
  • Koristi razne već postojeće spoljašnje programa da obavi posao.
  • Користи разне већ постојеће спољашње програма да обави посао.
  • Koristi razne već postojeće spoljašnje programa da obavi posao.
  • Drar nytta av redan tillgängliga externa program för att få jobbet gjort
  • İşlemlerin yapılabilmesi için zaten mevcut olan harici programlardan yararlanır
  • Використання доступних зовнішніх інструментів для виконання завдань.
  • xxMakes use of already available external programs to get its job donexx
  • 使用已有的外部程序完成任务
  • 利用已有的外部程式來完成其工作
https://www.kde.org/applications/system/kdepartitionmanager/ https://bugs.kde.org/enter_bug.cgi?format=guided&product=kdepartitionmanager https://docs.kde.org/?application=partitionmanager https://www.kde.org/images/screenshots/kdepartitionmanager.png KDE partitionmanager
diff --git a/src/org.kde.partitionmanager.desktop b/src/org.kde.partitionmanager.desktop index 15b97a7..40a22ca 100644 --- a/src/org.kde.partitionmanager.desktop +++ b/src/org.kde.partitionmanager.desktop @@ -1,190 +1,194 @@ [Desktop Entry] Type=Application Name=KDE Partition Manager Name[ar]=مدير أقسام كدي -Name[ast]=Xestor KDE de particiones +Name[ast]=Xestor de particiones de KDE Name[bg]=Управление на дялове за KDE Name[bs]=KDE‑ov menadžer particija Name[ca]=Gestor de particions del KDE Name[ca@valencia]=Gestor de particions del KDE Name[cs]=Správce diskových oddílů pro KDE Name[da]=KDE Partitionshåndtering Name[de]=KDE-Partitionsverwaltung Name[el]=Διαχειριστής κατατμήσεων του KDE Name[en_GB]=KDE Partition Manager Name[es]=Gestor de particiones de KDE Name[et]=KDE partitsioonihaldur Name[fi]=KDE:n osionhallinta Name[fr]=Gestionnaire de partitions de KDE Name[ga]=Bainisteoir Deighiltí KDE Name[gl]=Xestor de particións de KDE Name[hu]=KDE partíciókezelő Name[id]=KDE Partition Manager Name[it]=Gestore delle partizioni di KDE Name[ja]=KDE パーティションマネージャ Name[km]=កម្មវិធី​គ្រប់គ្រង​ការ​ចែកភាគ​ថាស​របស់ KDE Name[ko]=KDE 파티션 관리자 Name[lt]=KDE skaidinių tvarkyklė Name[lv]=KDE partīciju pārvaldnieks Name[mr]=केडीई विभाजन व्यवस्थापक Name[ms]=Pengurus Partisyen KDE Name[nb]=KDE partisjonshåndtering Name[nds]=KDE-Partitschonenpleger Name[nl]=KDE Partitiebeheerder -Name[nn]=KDE-partisjonshandtering +Name[nn]=Partisjonshandsaming for KDE Name[pa]=ਕੇਡੀਈ ਪਾਰਟੀਸ਼ਨ ਮੈਨੇਜਰ Name[pl]=Zarządzanie partycjami Name[pt]=Gestor de Partições do KDE Name[pt_BR]=Gerenciador de partições do KDE Name[ro]=Gestionarul de partiții KDE Name[ru]=Диспетчер разделов для KDE Name[sk]=KDE Správca partícií Name[sl]=Upravljalnik razdelkov za KDE Name[sr]=КДЕ‑ов менаџер партиција Name[sr@ijekavian]=КДЕ‑ов менаџер партиција Name[sr@ijekavianlatin]=KDE‑ov menadžer particija Name[sr@latin]=KDE‑ov menadžer particija Name[sv]=KDE:s partitionshanterare Name[th]=เครื่องมือจัดการพาร์ทิชันของ KDE Name[tr]=KDE Partition Manager Name[ug]=KDE دىسكا رايونى باشقۇرغۇ Name[uk]=Керування розділами диска KDE Name[x-test]=xxKDE Partition Managerxx Name[zh_CN]=KDE 分区管理器 Name[zh_TW]=KDE 磁碟分割區管理員 GenericName=Partition Editor GenericName[ar]=محرّر أقسام GenericName[ast]=Editor de particiones GenericName[bg]=Редактор на дялове GenericName[bs]=Uređivač particija GenericName[ca]=Editor de particions GenericName[ca@valencia]=Editor de particions GenericName[cs]=Editor diskových oddílů GenericName[da]=Partition-editor GenericName[de]=Partition-Editor GenericName[el]=Διαχειριστής κατατμήσεων GenericName[en_GB]=Partition Editor GenericName[es]=Editor de particiones GenericName[et]=Partitsioonihaldur GenericName[fi]=Osionhallinta GenericName[fr]=Éditeur de partitions GenericName[ga]=Eagarthóir Deighiltí GenericName[gl]=Editor de particións GenericName[hu]=Partíciószerkesztő GenericName[id]=Pengedit Partisi GenericName[it]=Editor delle partizioni GenericName[ja]=パーティション編集ツール GenericName[km]=កម្មវិធី​កែសម្រួល​ការ​ចែកភាគ​ថាស GenericName[ko]=파티션 편집기 GenericName[lt]=Skaidinių redaktorius GenericName[lv]=Partīciju pārvaldnieks GenericName[mr]=विभाजन संपादक GenericName[nb]=Partisjonsredigering GenericName[nds]=Partitschonen-Editor GenericName[nl]=Partitiebewerker GenericName[nn]=Partisjonsredigering GenericName[pa]=ਪਾਰਟੀਸ਼ਨ ਐਡੀਟਰ GenericName[pl]=Zarządzanie partycjami GenericName[pt]=Editor de Partições GenericName[pt_BR]=Editor de partições GenericName[ro]=Editor de partiții GenericName[ru]=Редактор разделов GenericName[sk]=Editor partícií GenericName[sl]=Urejevalnik razdelkov GenericName[sr]=Уређивач партиција GenericName[sr@ijekavian]=Уређивач партиција GenericName[sr@ijekavianlatin]=Uređivač particija GenericName[sr@latin]=Uređivač particija GenericName[sv]=Partitionseditor GenericName[th]=แก้ไขพาร์ทิชัน GenericName[tr]=Disk Bölümü Düzenleyici GenericName[ug]=دىسكا رايونى تەھرىرلىگۈچ GenericName[uk]=Редактор розділів диска GenericName[x-test]=xxPartition Editorxx GenericName[zh_CN]=分区编辑器 GenericName[zh_TW]=磁碟分割區編輯器 Comment=Manage disks, partitions and file systems Comment[ar]=أدِر الأقراص، والأقسام وأنظمة الملفّات Comment[ast]=Xestiona discos, particiones y sistemes de ficheros Comment[bg]=Управлява размерите на дискове, дялове и операционни системи Comment[bs]=Upravljajte diskovima, particijama i datotečnim sistemima Comment[ca]=Gestioneu discos, particions i sistemes de fitxers Comment[ca@valencia]=Gestioneu discos, particions i sistemes de fitxers Comment[cs]=Spravujte disky, oddíly a souborové systémy Comment[da]=Håndtér diske, partitioner og filsystemer Comment[de]=Verwaltung von Festplatten, Partitionen und Dateisystemen Comment[el]=Διαχείριση δίσκων, κατατμήσεων και συστημάτων αρχείων Comment[en_GB]=Manage disks, partitions and file systems Comment[es]=Gestionar discos, particiones y sistemas de archivos Comment[et]=Ketaste, partitsioonide ja failisüsteemide haldamine Comment[fi]=Hallitse levyjä, osioita ja tiedostojärjestelmiä Comment[fr]=Gère les disques, partitions et systèmes de fichiers Comment[ga]=Bainistigh dioscaí, deighiltí agus córais comhad Comment[gl]=Xestiona os discos, particións e o sistemas de ficheiros Comment[hu]=Lemezek, partíciók, és fájlrendszerek kezelése Comment[id]=Kelola disk, partisi dan sistem file Comment[it]=Gestisci dischi, partizioni e filesystem Comment[ja]=ディスク、パーティション、ファイルシステムを管理します Comment[km]=គ្រប់គ្រង​ថាស ការ​ចែកភាគ​ថាស និង​ប្រព័ន្ធ​ឯកសារ Comment[ko]=디스크, 파티션, 파일 시스템 관리 Comment[lt]=Tvarkykite diskus, skaidinius ir failų sistemas Comment[lv]=Pārvaldīt diskus, partīcijas un failu sistēmas Comment[mr]=डिस्क्स, विभाजन व फाईल प्रणाली व्यवस्थापन करा Comment[ms]=Urs cakera, partisyen dan sistem fail Comment[nb]=Styr disker, partisjoner og filsystemer Comment[nds]=Fastplaten, Partitschonen un Dateisystemen plegen Comment[nl]=Beheer schijven, partities en bestandssystemen Comment[nn]=Handter diskar, partisjonar og filsystem Comment[pa]=ਡਿਸਕਾਂ, ਪਾਰਟੀਸ਼ਨਾਂ ਅਤੇ ਫਾਇਲ ਸਿਸਟਮਾਂ ਦਾ ਪਰਬੰਧ ਕਰੋ Comment[pl]=Zarządzaj dyskami, partycjami i systemami plików Comment[pt]=Faz a gestão de discos, partições e sistemas de ficheiros Comment[pt_BR]=Gerencia discos, partições e sistemas de arquivos Comment[ro]=Gestionează discurile, partițiile și sistemele de fișiere Comment[ru]=Управление дисками, разделами и файловыми системами Comment[sk]=Spravuje disky, partície a súborové systémy Comment[sl]=Upravljajte z diski, razdelki in datotečnimi sistemi Comment[sr]=Управљајте дисковима, партицијама и фајл системима Comment[sr@ijekavian]=Управљајте дисковима, партицијама и фајл системима Comment[sr@ijekavianlatin]=Upravljajte diskovima, particijama i fajl sistemima Comment[sr@latin]=Upravljajte diskovima, particijama i fajl sistemima Comment[sv]=Hantera hårddiskar, partitioner och filsystem Comment[th]=จัดการดิสก์, พาร์ทิชัน และระบบแฟ้มต่าง ๆ ของคุณ Comment[tr]=Diskleri, disk bölümlerini ve dosya sistemlerini yönet Comment[ug]=دىسكىلارنى، دىسكا رايونلىرىنى ۋە ھۆججەت سىستېمىسىنى باشقۇرۇش پروگراممىسى Comment[uk]=Керуйте дисками, розділами та файловими системами Comment[x-test]=xxManage disks, partitions and file systemsxx Comment[zh_CN]=管理磁盘、分区和文件系统 Comment[zh_TW]=管理磁碟、分割區與檔案系統 Exec=partitionmanager Icon=partitionmanager Categories=System;Filesystem;KDE;Qt; X-KDE-StartupNotify=true Keywords=partition;disk; +Keywords[ast]=partición;discu; Keywords[ca]=partició;disc; Keywords[ca@valencia]=partició;disc; Keywords[cs]=oddíl;disk; Keywords[da]=partition;disk; Keywords[de]=partition;disk;festplatte Keywords[el]=κατάτμηση;δίσκος; Keywords[en_GB]=partition;disk; Keywords[es]=partición;disco; Keywords[fi]=osio;levy; Keywords[fr]=partition;disque; Keywords[gl]=partition;disk;partición;disco; Keywords[id]=partisi;disk; Keywords[it]=partizione;disco; Keywords[ko]=partition;disk;파티션;디스크; Keywords[lt]=skaidinys;diskas; Keywords[nl]=partitie;schijf +Keywords[nn]=partisjon;disk; Keywords[pl]=partycja;dysk; Keywords[pt]=partição;disco; +Keywords[pt_BR]=partição;disco; Keywords[sl]=razdelek;particija;disk; Keywords[sr]=partition;disk;партиција;диск; Keywords[sr@ijekavian]=partition;disk;партиција;диск; Keywords[sr@ijekavianlatin]=partition;disk;particija;disk; Keywords[sr@latin]=partition;disk;particija;disk; Keywords[sv]=partition;disk; Keywords[tr]=bölümleme;disk; Keywords[uk]=розділ;диск; Keywords[x-test]=xxpartitionxx;xxdiskxx; Keywords[zh_CN]=partition;disk;分区;磁盘; +Keywords[zh_TW]=partition;disk;分割區;磁碟;硬碟