diff --git a/src/widgets/renamedialog.cpp b/src/widgets/renamedialog.cpp index 00f7417f..1d092e53 100644 --- a/src/widgets/renamedialog.cpp +++ b/src/widgets/renamedialog.cpp @@ -1,779 +1,770 @@ /* This file is part of the KDE libraries Copyright (C) 2000 Stephan Kulow 1999 - 2008 David Faure 2001, 2006 Holger Freyther This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kio/renamedialog.h" #include "kio_widgets_debug.h" #include "../pathhelpers_p.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 #if 0 #include #endif #include #include using namespace KIO; static QLabel *createLabel(QWidget *parent, const QString &text, bool containerTitle = false) { QLabel *label = new QLabel(parent); if (containerTitle) { QFont font = label->font(); font.setBold(true); label->setFont(font); } label->setAlignment(Qt::AlignHCenter); label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); label->setText(text); return label; } static QLabel *createDateLabel(QWidget *parent, const KFileItem &item) { const QString text = i18n("Date: %1", item.timeString(KFileItem::ModificationTime)); return createLabel(parent, text); } static QLabel *createSizeLabel(QWidget *parent, const KFileItem &item) { const QString text = i18n("Size: %1", KIO::convertSize(item.size())); return createLabel(parent, text); } static KSqueezedTextLabel *createSqueezedLabel(QWidget *parent, const QString &text) { KSqueezedTextLabel *label = new KSqueezedTextLabel(text, parent); label->setAlignment(Qt::AlignHCenter); label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); return label; } static bool areFilesIdentical (const QString &fileName, const QString &secondFileName) { const qint64 bufferSize = 4096; // 4kb QByteArray res; QFile f(fileName); QFile f2(secondFileName); if (f.size() != f2.size()) { return false; } if (f.open(QFile::ReadOnly) && f2.open(QFile::ReadOnly)) { QCryptographicHash hash(QCryptographicHash::Sha1); char *buffer = new char[bufferSize]; - auto bytesRead = f.read(buffer, bufferSize); QCryptographicHash hash2(QCryptographicHash::Sha1); char *buffer2 = new char[bufferSize]; - auto bytesRead2 = f2.read(buffer2, bufferSize); - if (bytesRead != -1 && bytesRead2 != -1) { - // beginning of the files - hash.addData(qAsConst(buffer), bytesRead); - hash2.addData(qAsConst(buffer2), bytesRead2); - - if (hash.result() != hash2.result()) { - f.close(); - f2.close(); + bool result = true; + auto seekAddToHash = [](QCryptographicHash &hash, qint64 pos, QFile &f, char *buffer){ + auto ioresult = f.seek(pos); + int bytesRead; + if (ioresult) { + bytesRead = f.read(buffer, bufferSize); + ioresult = bytesRead != -1; + } + if (!ioresult) { + qCWarning(KIO_WIDGETS) << "Could not read to compare the file:" << f.fileName(); return false; } + hash.addData(qAsConst(buffer), bytesRead); + return true; + }; - if (f.size() > 2 * bufferSize) { - // compute a second hash in the middle of the file - f.seek(f.size() /2 - bufferSize); - auto bytesRead = f.read(buffer, bufferSize); - hash.addData(qAsConst(buffer), bytesRead); - - f2.seek(f.size() /2 - bufferSize); - auto bytesRead2 = f2.read(buffer2, bufferSize); - hash2.addData(qAsConst(buffer2), bytesRead2); - - if (hash.result() != hash2.result()) { - f.close(); - f2.close(); - return false; - } - } + // beginning of the files + result &= seekAddToHash(hash, 0, f, buffer); + result &= seekAddToHash(hash2, 0, f2, buffer2); - if (f.size() >= 2 * bufferSize) { - // compute a third hash for the end of the file - f.seek(f.size() - bufferSize); - auto bytesRead = f.read(buffer, bufferSize); - hash.addData(qAsConst(buffer), bytesRead); - - f2.seek(f.size() - bufferSize); - auto bytesRead2 = f2.read(buffer2, bufferSize); - hash2.addData(qAsConst(buffer2), bytesRead2); - - if (hash.result() != hash2.result()) { - f.close(); - f2.close(); - return false; - } - } + result |= hash.result() != hash2.result(); - f.close(); - f2.close(); - return true; - } else { - qCWarning(KIO_WIDGETS) << "Could not open to compare one of the files:" << fileName << secondFileName; + if (result && f.size() > 2 * bufferSize) { + // compute a second hash in the middle of the filev + result &= seekAddToHash(hash, f.size() / 2 - bufferSize, f, buffer); + result &= result && seekAddToHash(hash2, f.size() / 2 - bufferSize, f2, buffer2); + + result |= hash.result() != hash2.result(); + } + + if (result && f.size() > bufferSize) { + // compute a third hash for the end of the file + result &= seekAddToHash(hash, f.size() - bufferSize, f, buffer); + result &= seekAddToHash(hash2, f.size() - bufferSize, f2, buffer2); + + result |= hash.result() != hash2.result(); } + + f.close(); + f2.close(); + return result; + + } else { + qCWarning(KIO_WIDGETS) << "Could not open to compare one of the files:" << fileName << secondFileName; } return false; } /** @internal */ class Q_DECL_HIDDEN RenameDialog::RenameDialogPrivate { public: RenameDialogPrivate() { bCancel = nullptr; bRename = bSkip = bOverwrite = nullptr; bResume = bSuggestNewName = nullptr; bApplyAll = nullptr; m_pLineEdit = nullptr; m_srcPendingPreview = false; m_destPendingPreview = false; m_srcPreview = nullptr; m_destPreview = nullptr; m_srcArea = nullptr; m_destArea = nullptr; } void setRenameBoxText(const QString &fileName) { // sets the text in file name line edit box, selecting the filename (but not the extension if there is one). QMimeDatabase db; const QString extension = db.suffixForFileName(fileName); m_pLineEdit->setText(fileName); if (!extension.isEmpty()) { const int selectionLength = fileName.length() - extension.length() - 1; m_pLineEdit->setSelection(0, selectionLength); } else { m_pLineEdit->selectAll(); } } QPushButton *bCancel; QPushButton *bRename; QPushButton *bSkip; QPushButton *bOverwrite; QPushButton *bResume; QPushButton *bSuggestNewName; QCheckBox *bApplyAll; QLineEdit *m_pLineEdit; QUrl src; QUrl dest; bool m_srcPendingPreview; bool m_destPendingPreview; QLabel *m_srcPreview; QLabel *m_destPreview; QScrollArea *m_srcArea; QScrollArea *m_destArea; KFileItem srcItem; KFileItem destItem; }; RenameDialog::RenameDialog(QWidget *parent, const QString &_caption, const QUrl &_src, const QUrl &_dest, RenameDialog_Options _options, KIO::filesize_t sizeSrc, KIO::filesize_t sizeDest, const QDateTime &ctimeSrc, const QDateTime &ctimeDest, const QDateTime &mtimeSrc, const QDateTime &mtimeDest) : QDialog(parent), d(new RenameDialogPrivate) { setObjectName(QStringLiteral("KIO::RenameDialog")); d->src = _src; d->dest = _dest; setWindowTitle(_caption); d->bCancel = new QPushButton(this); KGuiItem::assign(d->bCancel, KStandardGuiItem::cancel()); connect(d->bCancel, &QAbstractButton::clicked, this, &RenameDialog::cancelPressed); if (_options & RenameDialog_MultipleItems) { d->bApplyAll = new QCheckBox(i18n("Appl&y to All"), this); d->bApplyAll->setToolTip((_options & RenameDialog_IsDirectory) ? i18n("When this is checked the button pressed will be applied to all subsequent folder conflicts for the remainder of the current job.\nUnless you press Skip you will still be prompted in case of a conflict with an existing file in the directory.") : i18n("When this is checked the button pressed will be applied to all subsequent conflicts for the remainder of the current job.")); connect(d->bApplyAll, &QAbstractButton::clicked, this, &RenameDialog::applyAllPressed); } if (!(_options & RenameDialog_NoRename)) { d->bRename = new QPushButton(i18n("&Rename"), this); d->bRename->setEnabled(false); d->bSuggestNewName = new QPushButton(i18n("Suggest New &Name"), this); connect(d->bSuggestNewName, &QAbstractButton::clicked, this, &RenameDialog::suggestNewNamePressed); connect(d->bRename, &QAbstractButton::clicked, this, &RenameDialog::renamePressed); } if ((_options & RenameDialog_MultipleItems) && (_options & RenameDialog_Skip)) { d->bSkip = new QPushButton(i18n("&Skip"), this); d->bSkip->setToolTip((_options & RenameDialog_IsDirectory) ? i18n("Do not copy or move this folder, skip to the next item instead") : i18n("Do not copy or move this file, skip to the next item instead")); connect(d->bSkip, &QAbstractButton::clicked, this, &RenameDialog::skipPressed); } if (_options & RenameDialog_Overwrite) { const QString text = (_options & RenameDialog_IsDirectory) ? i18nc("Write files into an existing folder", "&Write Into") : i18n("&Overwrite"); d->bOverwrite = new QPushButton(text, this); d->bOverwrite->setToolTip(i18n("Files and folders will be copied into the existing directory, alongside its existing contents.\nYou will be prompted again in case of a conflict with an existing file in the directory.")); connect(d->bOverwrite, &QAbstractButton::clicked, this, &RenameDialog::overwritePressed); } if (_options & RenameDialog_Resume) { d->bResume = new QPushButton(i18n("&Resume"), this); connect(d->bResume, &QAbstractButton::clicked, this, &RenameDialog::resumePressed); } QVBoxLayout *pLayout = new QVBoxLayout(this); pLayout->addStrut(400); // makes dlg at least that wide // User tries to overwrite a file with itself ? if (_options & RenameDialog_OverwriteItself) { QLabel *lb = new QLabel(i18n("This action would overwrite '%1' with itself.\n" "Please enter a new file name:", KStringHandler::csqueeze(d->src.toDisplayString(QUrl::PreferLocalFile), 100)), this); lb->setTextFormat(Qt::PlainText); d->bRename->setText(i18n("C&ontinue")); pLayout->addWidget(lb); } else if (_options & RenameDialog_Overwrite) { if (d->src.isLocalFile()) { d->srcItem = KFileItem(d->src); } else { UDSEntry srcUds; srcUds.reserve(4); srcUds.fastInsert(UDSEntry::UDS_NAME, d->src.fileName()); srcUds.fastInsert(UDSEntry::UDS_MODIFICATION_TIME, mtimeSrc.toMSecsSinceEpoch() / 1000); srcUds.fastInsert(UDSEntry::UDS_CREATION_TIME, ctimeSrc.toMSecsSinceEpoch() / 1000); srcUds.fastInsert(UDSEntry::UDS_SIZE, sizeSrc); d->srcItem = KFileItem(srcUds, d->src); } if (d->dest.isLocalFile()) { d->destItem = KFileItem(d->dest); } else { UDSEntry destUds; destUds.reserve(4); destUds.fastInsert(UDSEntry::UDS_NAME, d->dest.fileName()); destUds.fastInsert(UDSEntry::UDS_MODIFICATION_TIME, mtimeDest.toMSecsSinceEpoch() / 1000); destUds.fastInsert(UDSEntry::UDS_CREATION_TIME, ctimeDest.toMSecsSinceEpoch() / 1000); destUds.fastInsert(UDSEntry::UDS_SIZE, sizeDest); d->destItem = KFileItem(destUds, d->dest); } d->m_srcPreview = createLabel(parent, QString()); d->m_destPreview = createLabel(parent, QString()); QLabel *srcToDestArrow = createLabel(parent, QString()); d->m_srcPreview->setMinimumHeight(KIconLoader::SizeEnormous); d->m_destPreview->setMinimumHeight(KIconLoader::SizeEnormous); srcToDestArrow->setMinimumHeight(KIconLoader::SizeEnormous); d->m_srcPreview->setAlignment(Qt::AlignCenter); d->m_destPreview->setAlignment(Qt::AlignCenter); srcToDestArrow->setAlignment(Qt::AlignCenter); d->m_srcPendingPreview = true; d->m_destPendingPreview = true; // widget d->m_srcArea = createContainerLayout(parent, d->srcItem, d->m_srcPreview); d->m_destArea = createContainerLayout(parent, d->destItem, d->m_destPreview); connect(d->m_srcArea->verticalScrollBar(), &QAbstractSlider::valueChanged, d->m_destArea->verticalScrollBar(), &QAbstractSlider::setValue); connect(d->m_destArea->verticalScrollBar(), &QAbstractSlider::valueChanged, d->m_srcArea->verticalScrollBar(), &QAbstractSlider::setValue); connect(d->m_srcArea->horizontalScrollBar(), &QAbstractSlider::valueChanged, d->m_destArea->horizontalScrollBar(), &QAbstractSlider::setValue); connect(d->m_destArea->horizontalScrollBar(), &QAbstractSlider::valueChanged, d->m_srcArea->horizontalScrollBar(), &QAbstractSlider::setValue); // create layout QGridLayout *gridLayout = new QGridLayout(); pLayout->addLayout(gridLayout); int gridRow = 0; QLabel *titleLabel = new QLabel(i18n("This action will overwrite the destination."), this); gridLayout->addWidget(titleLabel, gridRow, 0, 1, 2); // takes the complete first line if (mtimeDest > mtimeSrc) { QLabel *warningLabel = new QLabel(i18n("Warning, the destination is more recent."), this); gridLayout->addWidget(warningLabel, ++gridRow, 0, 1, 2); } gridLayout->setRowMinimumHeight(++gridRow, 15); // spacer QLabel *srcTitle = createLabel(parent, i18n("Source"), true); gridLayout->addWidget(srcTitle, ++gridRow, 0); QLabel *destTitle = createLabel(parent, i18n("Destination"), true); gridLayout->addWidget(destTitle, gridRow, 2); QLabel *srcUrlLabel = createSqueezedLabel(parent, d->src.toDisplayString(QUrl::PreferLocalFile)); srcUrlLabel->setTextFormat(Qt::PlainText); gridLayout->addWidget(srcUrlLabel, ++gridRow, 0); QLabel *destUrlLabel = createSqueezedLabel(parent, d->dest.toDisplayString(QUrl::PreferLocalFile)); destUrlLabel->setTextFormat(Qt::PlainText); gridLayout->addWidget(destUrlLabel, gridRow, 2); // The labels containing previews or icons, and an arrow icon indicating // direction from src to dest const QString arrowName = qApp->isRightToLeft() ? QStringLiteral("go-previous") : QStringLiteral("go-next"); const QPixmap pix = QIcon::fromTheme(arrowName).pixmap(d->m_srcPreview->height()); srcToDestArrow->setPixmap(pix); gridLayout->addWidget(d->m_srcArea, ++gridRow, 0); gridLayout->addWidget(srcToDestArrow, gridRow, 1); gridLayout->addWidget(d->m_destArea, gridRow, 2); // check files checksum for local files if (d->dest.isLocalFile() && d->src.isLocalFile()) { const bool filesAreIdentical = areFilesIdentical(d->src.path(), d->dest.path()); QString text = filesAreIdentical ? i18n("The files' contents seem identical."): i18n("The files' contents are different."); QLabel* filesIdenticalLabel = createLabel(this, text, true); if (filesAreIdentical) { filesIdenticalLabel->setToolTip( i18n("Files' contents seem identical when they have the same size \nand they have the same 4kB chunks at the beginning, middle and end.") ); filesIdenticalLabel->setCursor(Qt::WhatsThisCursor); } gridLayout->addWidget(filesIdenticalLabel, ++gridRow, 2); } QLabel *srcDateLabel = createDateLabel(parent, d->srcItem); gridLayout->addWidget(srcDateLabel, ++gridRow, 0); QLabel *destDateLabel = createDateLabel(parent, d->destItem); gridLayout->addWidget(destDateLabel, gridRow, 2); QLabel *srcSizeLabel = createSizeLabel(parent, d->srcItem); gridLayout->addWidget(srcSizeLabel, ++gridRow, 0); QLabel *destSizeLabel = createSizeLabel(parent, d->destItem); gridLayout->addWidget(destSizeLabel, gridRow, 2); } else { // This is the case where we don't want to allow overwriting, the existing // file must be preserved (e.g. when renaming). QString sentence1; if (mtimeDest < mtimeSrc) { sentence1 = i18n("An older item named '%1' already exists.", d->dest.toDisplayString(QUrl::PreferLocalFile)); } else if (mtimeDest == mtimeSrc) { sentence1 = i18n("A similar file named '%1' already exists.", d->dest.toDisplayString(QUrl::PreferLocalFile)); } else { sentence1 = i18n("A more recent item named '%1' already exists.", d->dest.toDisplayString(QUrl::PreferLocalFile)); } QLabel *lb = new KSqueezedTextLabel(sentence1, this); lb->setTextFormat(Qt::PlainText); pLayout->addWidget(lb); } if (!(_options & RenameDialog_OverwriteItself) && !(_options & RenameDialog_NoRename)) { if (_options & RenameDialog_Overwrite) { pLayout->addSpacing(15); // spacer } QLabel *lb2 = new QLabel(i18n("Rename:"), this); pLayout->addWidget(lb2); } QHBoxLayout *layout2 = new QHBoxLayout(); pLayout->addLayout(layout2); d->m_pLineEdit = new QLineEdit(this); layout2->addWidget(d->m_pLineEdit); if (d->bRename) { const QString fileName = d->dest.fileName(); d->setRenameBoxText(KIO::decodeFileName(fileName)); connect(d->m_pLineEdit, &QLineEdit::textChanged, this, &RenameDialog::enableRenameButton); d->m_pLineEdit->setFocus(); } else { d->m_pLineEdit->hide(); } if (d->bSuggestNewName) { layout2->addWidget(d->bSuggestNewName); setTabOrder(d->m_pLineEdit, d->bSuggestNewName); } KSeparator *separator = new KSeparator(this); pLayout->addWidget(separator); QHBoxLayout *layout = new QHBoxLayout(); pLayout->addLayout(layout); layout->addStretch(1); if (d->bApplyAll) { layout->addWidget(d->bApplyAll); setTabOrder(d->bApplyAll, d->bCancel); } if (d->bRename) { layout->addWidget(d->bRename); setTabOrder(d->bRename, d->bCancel); } if (d->bSkip) { layout->addWidget(d->bSkip); setTabOrder(d->bSkip, d->bCancel); } if (d->bOverwrite) { layout->addWidget(d->bOverwrite); setTabOrder(d->bOverwrite, d->bCancel); } if (d->bResume) { layout->addWidget(d->bResume); setTabOrder(d->bResume, d->bCancel); } d->bCancel->setDefault(true); layout->addWidget(d->bCancel); resize(sizeHint()); #if 1 // without kfilemetadata // don't wait for kfilemetadata, but wait until the layouting is done if (_options & RenameDialog_Overwrite) { QMetaObject::invokeMethod(this, "resizePanels", Qt::QueuedConnection); } #endif } RenameDialog::~RenameDialog() { delete d; } void RenameDialog::enableRenameButton(const QString &newDest) { if (newDest != KIO::decodeFileName(d->dest.fileName()) && !newDest.isEmpty()) { d->bRename->setEnabled(true); d->bRename->setDefault(true); if (d->bOverwrite) { d->bOverwrite->setEnabled(false); // prevent confusion (#83114) } } else { d->bRename->setEnabled(false); if (d->bOverwrite) { d->bOverwrite->setEnabled(true); } } } QUrl RenameDialog::newDestUrl() { const QString fileName = d->m_pLineEdit->text(); QUrl newDest = d->dest.adjusted(QUrl::RemoveFilename); // keeps trailing slash newDest.setPath(newDest.path() + KIO::encodeFileName(fileName)); return newDest; } QUrl RenameDialog::autoDestUrl() const { const QUrl destDirectory = d->dest.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash); const QString newName = KFileUtils::suggestName(destDirectory, d->dest.fileName()); QUrl newDest(destDirectory); newDest.setPath(concatPaths(newDest.path(), newName)); return newDest; } void RenameDialog::cancelPressed() { done(Result_Cancel); } // Rename void RenameDialog::renamePressed() { if (d->m_pLineEdit->text().isEmpty()) { return; } if (d->bApplyAll && d->bApplyAll->isChecked()) { done(Result_AutoRename); } else { const QUrl u = newDestUrl(); if (!u.isValid()) { KMessageBox::error(this, i18n("Malformed URL\n%1", u.errorString())); qCWarning(KIO_WIDGETS) << u.errorString(); return; } done(Result_Rename); } } #if KIOWIDGETS_BUILD_DEPRECATED_SINCE(5, 0) QString RenameDialog::suggestName(const QUrl &baseURL, const QString &oldName) { return KFileUtils::suggestName(baseURL, oldName); } #endif // Propose button clicked void RenameDialog::suggestNewNamePressed() { /* no name to play with */ if (d->m_pLineEdit->text().isEmpty()) { return; } QUrl destDirectory = d->dest.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash); d->setRenameBoxText(KFileUtils::suggestName(destDirectory, d->m_pLineEdit->text())); } void RenameDialog::skipPressed() { if (d->bApplyAll && d->bApplyAll->isChecked()) { done(Result_AutoSkip); } else { done(Result_Skip); } } void RenameDialog::autoSkipPressed() { done(Result_AutoSkip); } void RenameDialog::overwritePressed() { if (d->bApplyAll && d->bApplyAll->isChecked()) { done(Result_OverwriteAll); } else { done(Result_Overwrite); } } void RenameDialog::overwriteAllPressed() { done(Result_OverwriteAll); } void RenameDialog::resumePressed() { if (d->bApplyAll && d->bApplyAll->isChecked()) { done(Result_ResumeAll); } else { done(Result_Resume); } } void RenameDialog::resumeAllPressed() { done(Result_ResumeAll); } void RenameDialog::applyAllPressed() { if (d->bApplyAll && d->bApplyAll->isChecked()) { d->m_pLineEdit->setText(KIO::decodeFileName(d->dest.fileName())); d->m_pLineEdit->setEnabled(false); if (d->bRename) { d->bRename->setEnabled(true); } if (d->bSuggestNewName) { d->bSuggestNewName->setEnabled(false); } } else { d->m_pLineEdit->setEnabled(true); if (d->bRename) { d->bRename->setEnabled(false); } if (d->bSuggestNewName) { d->bSuggestNewName->setEnabled(true); } } } void RenameDialog::showSrcIcon(const KFileItem &fileitem) { // The preview job failed, show a standard file icon. d->m_srcPendingPreview = false; const int size = d->m_srcPreview->height(); const QPixmap pix = QIcon::fromTheme(fileitem.iconName(), QIcon::fromTheme(QStringLiteral("application-octet-stream"))).pixmap(size); d->m_srcPreview->setPixmap(pix); } void RenameDialog::showDestIcon(const KFileItem &fileitem) { // The preview job failed, show a standard file icon. d->m_destPendingPreview = false; const int size = d->m_destPreview->height(); const QPixmap pix = QIcon::fromTheme(fileitem.iconName(), QIcon::fromTheme(QStringLiteral("application-octet-stream"))).pixmap(size); d->m_destPreview->setPixmap(pix); } void RenameDialog::showSrcPreview(const KFileItem &fileitem, const QPixmap &pixmap) { Q_UNUSED(fileitem); if (d->m_srcPendingPreview) { d->m_srcPreview->setPixmap(pixmap); d->m_srcPendingPreview = false; } } void RenameDialog::showDestPreview(const KFileItem &fileitem, const QPixmap &pixmap) { Q_UNUSED(fileitem); if (d->m_destPendingPreview) { d->m_destPreview->setPixmap(pixmap); d->m_destPendingPreview = false; } } void RenameDialog::resizePanels() { Q_ASSERT(d->m_srcArea != nullptr); Q_ASSERT(d->m_destArea != nullptr); Q_ASSERT(d->m_srcPreview != nullptr); Q_ASSERT(d->m_destPreview != nullptr); // using QDesktopWidget geometry as Kephal isn't accessible here in kdelibs const QSize screenSize = QApplication::desktop()->availableGeometry(this).size(); QSize halfSize = d->m_srcArea->widget()->sizeHint().expandedTo(d->m_destArea->widget()->sizeHint()); const QSize currentSize = d->m_srcArea->size().expandedTo(d->m_destArea->size()); const int maxHeightPossible = screenSize.height() - (size().height() - currentSize.height()); QSize maxHalfSize = QSize(screenSize.width() / qreal(2.1), maxHeightPossible * qreal(0.9)); if (halfSize.height() > maxHalfSize.height() && halfSize.width() <= maxHalfSize.width() + d->m_srcArea->verticalScrollBar()->width()) { halfSize.rwidth() += d->m_srcArea->verticalScrollBar()->width(); maxHalfSize.rwidth() += d->m_srcArea->verticalScrollBar()->width(); } d->m_srcArea->setMinimumSize(halfSize.boundedTo(maxHalfSize)); d->m_destArea->setMinimumSize(halfSize.boundedTo(maxHalfSize)); KIO::PreviewJob *srcJob = KIO::filePreview(KFileItemList() << d->srcItem, QSize(d->m_srcPreview->width() * qreal(0.9), d->m_srcPreview->height())); srcJob->setScaleType(KIO::PreviewJob::Unscaled); KIO::PreviewJob *destJob = KIO::filePreview(KFileItemList() << d->destItem, QSize(d->m_destPreview->width() * qreal(0.9), d->m_destPreview->height())); destJob->setScaleType(KIO::PreviewJob::Unscaled); connect(srcJob, &PreviewJob::gotPreview, this, &RenameDialog::showSrcPreview); connect(destJob, &PreviewJob::gotPreview, this, &RenameDialog::showDestPreview); connect(srcJob, &PreviewJob::failed, this, &RenameDialog::showSrcIcon); connect(destJob, &PreviewJob::failed, this, &RenameDialog::showDestIcon); } QScrollArea *RenameDialog::createContainerLayout(QWidget *parent, const KFileItem &item, QLabel *preview) { #if 0 // PENDING KFileItemList itemList; itemList << item; // KFileMetaDataWidget was deprecated for a Nepomuk widget, which is itself deprecated... // If we still want metadata shown, we need a plugin that fetches data from KFileMetaData::ExtractorCollection KFileMetaDataWidget *metaWidget = new KFileMetaDataWidget(this); metaWidget->setReadOnly(true); metaWidget->setItems(itemList); // ### This is going to call resizePanels twice! Need to split it up to do preview job only once on each side connect(metaWidget, SIGNAL(metaDataRequestFinished(KFileItemList)), this, SLOT(resizePanels())); #endif // Encapsulate the MetaDataWidgets inside a container with stretch at the bottom. // This prevents that the meta data widgets get vertically stretched // in the case where the height of m_metaDataArea > m_metaDataWidget. QWidget *widgetContainer = new QWidget(parent); QVBoxLayout *containerLayout = new QVBoxLayout(widgetContainer); containerLayout->setContentsMargins(0, 0, 0, 0); containerLayout->setSpacing(0); containerLayout->addWidget(preview); #if 0 // PENDING containerLayout->addWidget(metaWidget); #endif containerLayout->addStretch(1); QScrollArea *metaDataArea = new QScrollArea(parent); metaDataArea->setWidget(widgetContainer); metaDataArea->setWidgetResizable(true); metaDataArea->setFrameShape(QFrame::NoFrame); return metaDataArea; }