diff --git a/krusader/Archive/abstractthreadedjob.cpp b/krusader/Archive/abstractthreadedjob.cpp
index 28175755..f8fc6945 100644
--- a/krusader/Archive/abstractthreadedjob.cpp
+++ b/krusader/Archive/abstractthreadedjob.cpp
@@ -1,664 +1,664 @@
/*****************************************************************************
* Copyright (C) 2009 Csaba Karai *
* Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "abstractthreadedjob.h"
// QtCore
#include
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include "krarchandler.h"
#include "../krglobal.h"
#include "../krservices.h"
#include "../FileSystem/filesystemprovider.h"
extern KRarcHandler arcHandler;
AbstractThreadedJob::AbstractThreadedJob() : KIO::Job(), _locker(), _waiter(), _stack(), _maxProgressValue(0),
_currentProgress(0), _exiting(false), _jobThread(0)
{
}
void AbstractThreadedJob::startAbstractJobThread(AbstractJobThread * jobThread)
{
_jobThread = jobThread;
_jobThread->setJob(this);
_jobThread->moveToThread(_jobThread);
_jobThread->start();
}
AbstractThreadedJob::~AbstractThreadedJob()
{
_exiting = true;
if (_jobThread) {
_jobThread->abort();
_locker.lock();
_waiter.wakeAll();
_locker.unlock();
_jobThread->wait();
delete _jobThread;
}
}
bool AbstractThreadedJob::event(QEvent *e)
{
if (e->type() == QEvent::User) {
UserEvent *event = (UserEvent*) e;
switch (event->command()) {
case CMD_SUCCESS: {
emitResult();
}
break;
case CMD_ERROR: {
int error = event->args()[ 0 ].value();
QString errorText = event->args()[ 1 ].value();
setError(error);
setErrorText(errorText);
emitResult();
}
break;
case CMD_INFO: {
QString info = event->args()[ 0 ].value();
QString arg1 = event->args()[ 1 ].value();
QString arg2 = event->args()[ 2 ].value();
QString arg3 = event->args()[ 3 ].value();
QString arg4 = event->args()[ 4 ].value();
_title = info;
emit description(this, info,
qMakePair(arg1, arg2),
qMakePair(arg3, arg4));
}
break;
case CMD_RESET: {
QString info = event->args()[ 0 ].value();
QString arg1 = event->args()[ 1 ].value();
QString arg2 = event->args()[ 2 ].value();
QString arg3 = event->args()[ 3 ].value();
QString arg4 = event->args()[ 4 ].value();
_title = info;
setProcessedAmount(KJob::Bytes, 0);
setTotalAmount(KJob::Bytes, 0);
emitSpeed(0);
emit description(this, info,
qMakePair(arg1, arg2),
qMakePair(arg3, arg4));
}
break;
case CMD_UPLOAD_FILES:
case CMD_DOWNLOAD_FILES: {
QList sources = KrServices::toUrlList(event->args()[ 0 ].value());
QUrl dest = event->args()[ 1 ].value();
KIO::Job *job = KIO::copy(sources, dest, KIO::HideProgressInfo);
addSubjob(job);
job->setUiDelegate(new KIO::JobUiDelegate());
connect(job, &KIO::Job::result, this, &AbstractThreadedJob::slotDownloadResult);
connect(job, SIGNAL(processedAmount(KJob*,KJob::Unit,qulonglong)),
this, SLOT(slotProcessedAmount(KJob*,KJob::Unit,qulonglong)));
connect(job, SIGNAL(totalAmount(KJob*,KJob::Unit,qulonglong)),
this, SLOT(slotTotalAmount(KJob*,KJob::Unit,qulonglong)));
connect(job, SIGNAL(speed(KJob*,ulong)),
this, SLOT(slotSpeed(KJob*,ulong)));
connect(job, SIGNAL(description(KJob*,QString,QPair,QPair)),
this, SLOT(slotDescription(KJob*,QString,QPair,QPair)));
}
break;
case CMD_MAXPROGRESSVALUE: {
qulonglong maxValue = event->args()[ 0 ].value();
_maxProgressValue = maxValue;
_currentProgress = 0;
}
break;
case CMD_ADD_PROGRESS: {
qulonglong progress = event->args()[ 0 ].value();
_currentProgress += progress;
if (_maxProgressValue != 0) {
setPercent(100 * _currentProgress / _maxProgressValue);
int elapsed = _time.isNull() ? 1 : _time.secsTo(QTime::currentTime());
if (elapsed != 0 && event->args().count() > 1) {
_time = QTime::currentTime();
QString progressString = (event->args()[ 1 ].value());
emit description(this, _title,
qMakePair(progressString, QString("%1/%2").arg(_currentProgress).arg(_maxProgressValue)),
qMakePair(QString(), QString())
);
}
}
}
break;
case CMD_GET_PASSWORD: {
QString path = event->args()[ 0 ].value();
QString password = KRarcHandler::getPassword(path);
QList *resultResp = new QList ();
(*resultResp) << password;
addEventResponse(resultResp);
}
break;
case CMD_MESSAGE: {
QString message = event->args()[ 0 ].value();
KIO::JobUiDelegate *ui = static_cast(uiDelegate());
KMessageBox::information(ui ? ui->window() : 0, message);
QList *resultResp = new QList ();
addEventResponse(resultResp);
}
break;
}
return true;
} else {
return KIO::Job::event(e);
}
}
void AbstractThreadedJob::addEventResponse(QList * obj)
{
_locker.lock();
_stack.push(obj);
_waiter.wakeOne();
_locker.unlock();
}
QList * AbstractThreadedJob::getEventResponse(UserEvent * event)
{
_locker.lock();
QApplication::postEvent(this, event);
_waiter.wait(&_locker);
if (_exiting)
return 0;
QList *resp = _stack.pop();
_locker.unlock();
return resp;
}
void AbstractThreadedJob::sendEvent(UserEvent * event)
{
QApplication::postEvent(this, event);
}
void AbstractThreadedJob::slotDownloadResult(KJob* job)
{
QList *resultResp = new QList ();
if (job) {
(*resultResp) << QVariant(job->error());
(*resultResp) << QVariant(job->errorText());
} else {
(*resultResp) << QVariant(KJob::UserDefinedError);
(*resultResp) << QVariant(QString(i18n("Internal error, undefined in result signal")));
}
addEventResponse(resultResp);
}
void AbstractThreadedJob::slotProcessedAmount(KJob *, KJob::Unit unit, qulonglong xu)
{
setProcessedAmount(unit, xu);
}
void AbstractThreadedJob::slotTotalAmount(KJob *, KJob::Unit unit, qulonglong xu)
{
setTotalAmount(unit, xu);
}
void AbstractThreadedJob::slotSpeed(KJob *, unsigned long spd)
{
emitSpeed(spd);
}
void AbstractThreadedJob::slotDescription(KJob *, const QString &title, const QPair &field1,
const QPair &field2)
{
QString mytitle = title;
if (!_title.isNull())
mytitle = _title;
emit description(this, mytitle, field1, field2);
}
class AbstractJobObserver : public KRarcObserver
{
protected:
AbstractJobThread * _jobThread;
public:
explicit AbstractJobObserver(AbstractJobThread * thread): _jobThread(thread) {}
virtual ~AbstractJobObserver() {}
virtual void processEvents() Q_DECL_OVERRIDE {
usleep(1000);
qApp->processEvents();
}
virtual void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE {
_jobThread->sendReset(jobTitle);
_jobThread->sendMaxProgressValue(count);
}
virtual void subJobStopped() Q_DECL_OVERRIDE {
}
virtual bool wasCancelled() Q_DECL_OVERRIDE {
return _jobThread->_exited;
}
virtual void error(const QString & error) Q_DECL_OVERRIDE {
_jobThread->sendError(KIO::ERR_NO_CONTENT, error);
}
virtual void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE {
_jobThread->sendError(KIO::ERR_NO_CONTENT, error + '\n' + details);
}
virtual void incrementProgress(int c) Q_DECL_OVERRIDE {
_jobThread->sendAddProgress(c, _jobThread->_progressTitle);
}
};
AbstractJobThread::AbstractJobThread() : _job(0), _downloadTempDir(0), _observer(0), _tempFile(0),
_tempDir(0), _exited(false)
{
}
AbstractJobThread::~AbstractJobThread()
{
if (_downloadTempDir) {
delete _downloadTempDir;
_downloadTempDir = 0;
}
if (_observer) {
delete _observer;
_observer = 0;
}
if (_tempFile) {
delete _tempFile;
_tempFile = 0;
}
}
void AbstractJobThread::run()
{
- QTimer::singleShot(0, this, SLOT(slotStart()));
+ QTimer::singleShot(0, this, &AbstractJobThread::slotStart);
QPointer threadLoop = new QEventLoop(this);
_loop = threadLoop;
threadLoop->exec();
_loop = 0;
delete threadLoop;
}
void AbstractJobThread::terminate()
{
if (_loop && !_exited) {
_loop->quit();
_exited = true;
}
}
void AbstractJobThread::abort()
{
terminate();
}
QList AbstractJobThread::remoteUrls(const QUrl &baseUrl, const QStringList & files)
{
QList urlList;
foreach(const QString &name, files) {
QUrl url = baseUrl;
url = url.adjusted(QUrl::StripTrailingSlash);
url.setPath(url.path() + '/' + (name));
urlList << url;
}
return urlList;
}
QUrl AbstractJobThread::downloadIfRemote(const QUrl &baseUrl, const QStringList & files)
{
// download remote URL-s if necessary
if (!baseUrl.isLocalFile()) {
sendInfo(i18n("Downloading remote files"));
_downloadTempDir = new QTemporaryDir();
QList urlList = remoteUrls(baseUrl, files);
QUrl dest(_downloadTempDir->path());
QList args;
args << KrServices::toStringList(urlList);
args << dest;
UserEvent * downloadEvent = new UserEvent(CMD_DOWNLOAD_FILES, args);
QList * result = _job->getEventResponse(downloadEvent);
if (result == 0)
return QUrl();
int errorCode = (*result)[ 0 ].value();
QString errorText = (*result)[ 1 ].value();
delete result;
if (errorCode) {
sendError(errorCode, errorText);
return QUrl();
} else {
return dest;
}
} else {
return baseUrl;
}
}
QString AbstractJobThread::tempFileIfRemote(const QUrl &kurl, const QString &type)
{
if (kurl.isLocalFile()) {
return kurl.path();
}
_tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.") + type);
_tempFile->open();
_tempFileName = _tempFile->fileName();
_tempFile->close(); // necessary to create the filename
QFile::remove(_tempFileName);
_tempFileTarget = kurl;
return _tempFileName;
}
QString AbstractJobThread::tempDirIfRemote(const QUrl &kurl)
{
if (kurl.isLocalFile()) {
return kurl.adjusted(QUrl::StripTrailingSlash).path();
}
_tempDir = new QTemporaryDir();
_tempDirTarget = kurl;
return _tempDirName = _tempDir->path();
}
void AbstractJobThread::sendSuccess()
{
terminate();
QList args;
UserEvent * errorEvent = new UserEvent(CMD_SUCCESS, args);
_job->sendEvent(errorEvent);
}
void AbstractJobThread::sendError(int errorCode, QString message)
{
terminate();
QList args;
args << errorCode;
args << message;
UserEvent * errorEvent = new UserEvent(CMD_ERROR, args);
_job->sendEvent(errorEvent);
}
void AbstractJobThread::sendInfo(QString message, QString a1, QString a2, QString a3, QString a4)
{
QList args;
args << message;
args << a1;
args << a2;
args << a3;
args << a4;
UserEvent * infoEvent = new UserEvent(CMD_INFO, args);
_job->sendEvent(infoEvent);
}
void AbstractJobThread::sendReset(QString message, QString a1, QString a2, QString a3, QString a4)
{
QList args;
args << message;
args << a1;
args << a2;
args << a3;
args << a4;
UserEvent * infoEvent = new UserEvent(CMD_RESET, args);
_job->sendEvent(infoEvent);
}
void AbstractJobThread::sendMaxProgressValue(qulonglong value)
{
QList args;
args << value;
UserEvent * infoEvent = new UserEvent(CMD_MAXPROGRESSVALUE, args);
_job->sendEvent(infoEvent);
}
void AbstractJobThread::sendAddProgress(qulonglong value, const QString &progress)
{
QList args;
args << value;
if (!progress.isNull())
args << progress;
UserEvent * infoEvent = new UserEvent(CMD_ADD_PROGRESS, args);
_job->sendEvent(infoEvent);
}
void countFiles(const QString &path, unsigned long &totalFiles, bool &stop)
{
const QDir dir(path);
if (!dir.exists()) {
totalFiles++; // assume it's a file
return;
}
for (const QString name : dir.entryList()) {
if (stop)
return;
if (name == QStringLiteral(".") || name == QStringLiteral(".."))
continue;
countFiles(dir.absoluteFilePath(name), totalFiles, stop);
}
}
void AbstractJobThread::countLocalFiles(const QUrl &baseUrl, const QStringList &names,
unsigned long &totalFiles)
{
sendReset(i18n("Counting files"));
FileSystem *calcSpaceFileSystem = FileSystemProvider::instance().getFilesystem(baseUrl);
calcSpaceFileSystem->scanDir(baseUrl);
for (const QString name : names) {
if (_exited)
return;
const QString path = calcSpaceFileSystem->getUrl(name).toLocalFile();
if (!QFileInfo(path).exists())
return;
countFiles(path, totalFiles, _exited);
}
delete calcSpaceFileSystem;
}
KRarcObserver * AbstractJobThread::observer()
{
if (_observer)
return _observer;
_observer = new AbstractJobObserver(this);
return _observer;
}
bool AbstractJobThread::uploadTempFiles()
{
if (_tempFile != 0 || _tempDir != 0) {
sendInfo(i18n("Uploading to remote destination"));
if (_tempFile) {
QList urlList;
urlList << QUrl::fromLocalFile(_tempFileName);
QList args;
args << KrServices::toStringList(urlList);
args << _tempFileTarget;
UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args);
QList * result = _job->getEventResponse(uploadEvent);
if (result == 0)
return false;
int errorCode = (*result)[ 0 ].value();
QString errorText = (*result)[ 1 ].value();
delete result;
if (errorCode) {
sendError(errorCode, errorText);
return false;
}
}
if (_tempDir) {
QList urlList;
QDir tempDir(_tempDirName);
QStringList list = tempDir.entryList();
foreach(const QString &name, list) {
if (name == "." || name == "..")
continue;
QUrl url = QUrl::fromLocalFile(_tempDirName).adjusted(QUrl::StripTrailingSlash);
url.setPath(url.path() + '/' + (name));
urlList << url;
}
QList args;
args << KrServices::toStringList(urlList);
args << _tempDirTarget;
UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args);
QList * result = _job->getEventResponse(uploadEvent);
if (result == 0)
return false;
int errorCode = (*result)[ 0 ].value();
QString errorText = (*result)[ 1 ].value();
delete result;
if (errorCode) {
sendError(errorCode, errorText);
return false;
}
}
}
return true;
}
QString AbstractJobThread::getPassword(const QString &path)
{
QList args;
args << path;
UserEvent * getPasswdEvent = new UserEvent(CMD_GET_PASSWORD, args);
QList * result = _job->getEventResponse(getPasswdEvent);
if (result == 0)
return QString();
QString password = (*result)[ 0 ].value();
if (password.isNull())
password = QString("");
delete result;
return password;
}
void AbstractJobThread::sendMessage(const QString &message)
{
QList args;
args << message;
UserEvent * getPasswdEvent = new UserEvent(CMD_MESSAGE, args);
QList * result = _job->getEventResponse(getPasswdEvent);
if (result == 0)
return;
delete result;
}
//! Gets some archive information that is needed in several cases.
/*!
\param path A path to the archive.
\param type The type of the archive.
\param password The password of the archive.
\param arcName The name of the archive.
\param sourceFolder A QUrl, which may be remote, of the folder where the archive is.
\return If the archive information has been obtained.
*/
bool AbstractJobThread::getArchiveInformation(QString &path, QString &type, QString &password,
QString &arcName, const QUrl &sourceFolder)
{
// Safety checks (though the user shouldn't have been able to select something named "" or "..")
if (arcName.isEmpty())
return false;
if (arcName == "..")
return false;
QUrl url = sourceFolder.adjusted(QUrl::StripTrailingSlash);
url.setPath(url.path() + '/' + arcName);
path = url.adjusted(QUrl::StripTrailingSlash).path();
QMimeDatabase db;
QMimeType mt = db.mimeTypeForUrl(url);
QString mime = mt.isValid() ? mt.name() : QString();
bool encrypted = false;
type = arcHandler.getType(encrypted, path, mime);
// Check that the archive is supported
if (!KRarcHandler::arcSupported(type)) {
sendError(KIO::ERR_NO_CONTENT, i18nc("%1=archive filename", "%1, unsupported archive type.", arcName));
return false;
}
password = encrypted ? getPassword(path) : QString();
return true;
}
diff --git a/krusader/Dialogs/krpleasewait.cpp b/krusader/Dialogs/krpleasewait.cpp
index dbf3fb18..13a9ef9f 100644
--- a/krusader/Dialogs/krpleasewait.cpp
+++ b/krusader/Dialogs/krpleasewait.cpp
@@ -1,156 +1,156 @@
/*****************************************************************************
* Copyright (C) 2000 Shie Erlich *
* Copyright (C) 2000 Rafi Yanai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "krpleasewait.h"
// QtCore
#include
#include
// QtGui
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include "../krglobal.h"
KRPleaseWait::KRPleaseWait(QString msg, QWidget *parent, int count, bool cancel):
QProgressDialog(cancel ? 0 : parent) , inc(true)
{
setModal(!cancel);
timer = new QTimer(this);
setWindowTitle(i18n("Krusader::Wait"));
setMinimumDuration(500);
setAutoClose(false);
setAutoReset(false);
connect(timer, &QTimer::timeout, this, &KRPleaseWait::cycleProgress);
QProgressBar* progress = new QProgressBar(this);
progress->setMaximum(count);
progress->setMinimum(0);
setBar(progress);
QLabel* label = new QLabel(this);
setLabel(label);
QPushButton* btn = new QPushButton(i18n("&Cancel"), this);
setCancelButton(btn);
btn->setEnabled(canClose = cancel);
setLabelText(msg);
show();
}
void KRPleaseWait::closeEvent(QCloseEvent * e)
{
if (canClose) {
emit canceled();
e->accept();
} else /* if cancel is not allowed, we disable */
e->ignore(); /* the window closing [x] also */
}
void KRPleaseWait::incProgress(int howMuch)
{
setValue(value() + howMuch);
}
void KRPleaseWait::cycleProgress()
{
if (inc) setValue(value() + 1);
else setValue(value() - 1);
if (value() >= 9) inc = false;
if (value() <= 0) inc = true;
}
KRPleaseWaitHandler::KRPleaseWaitHandler(QWidget *parentWindow)
: QObject(parentWindow), _parentWindow(parentWindow), job(), dlg(0)
{
}
void KRPleaseWaitHandler::stopWait()
{
if (dlg != 0) delete dlg;
dlg = 0;
cycleMutex = incMutex = false;
// return cursor to normal arrow
_parentWindow->setCursor(Qt::ArrowCursor);
}
void KRPleaseWaitHandler::startWaiting(QString msg, int count , bool cancel)
{
if (dlg == 0) {
dlg = new KRPleaseWait(msg , _parentWindow, count, cancel);
connect(dlg, &KRPleaseWait::canceled, this, &KRPleaseWaitHandler::killJob);
}
incMutex = cycleMutex = _wasCancelled = false;
dlg->setValue(0);
dlg->setLabelText(msg);
if (count == 0) {
dlg->setMaximum(10);
cycle = true;
cycleProgress();
} else {
dlg->setMaximum(count);
cycle = false;
}
}
void KRPleaseWaitHandler::cycleProgress()
{
if (cycleMutex) return;
cycleMutex = true;
if (dlg) dlg->cycleProgress();
- if (cycle) QTimer::singleShot(2000, this, SLOT(cycleProgress()));
+ if (cycle) QTimer::singleShot(2000, this, &KRPleaseWaitHandler::cycleProgress);
cycleMutex = false;
}
void KRPleaseWaitHandler::killJob()
{
if (!job.isNull()) job->kill(KJob::EmitResult);
stopWait();
_wasCancelled = true;
}
void KRPleaseWaitHandler::setJob(KIO::Job* j)
{
job = j;
}
void KRPleaseWaitHandler::incProgress(int i)
{
if (incMutex) return;
incMutex = true;
if (dlg) dlg->incProgress(i);
incMutex = false;
}
diff --git a/krusader/DiskUsage/diskusagegui.cpp b/krusader/DiskUsage/diskusagegui.cpp
index 306bc4d9..36ba3bc8 100644
--- a/krusader/DiskUsage/diskusagegui.cpp
+++ b/krusader/DiskUsage/diskusagegui.cpp
@@ -1,242 +1,242 @@
/*****************************************************************************
* Copyright (C) 2004 Csaba Karai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "diskusagegui.h"
// QtCore
#include
// QtGui
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include "../krglobal.h"
#include "../icon.h"
#include "../FileSystem/filesystem.h"
#include "../Dialogs/krdialogs.h"
DiskUsageGUI::DiskUsageGUI(const QUrl &openDir)
: QDialog(nullptr), exitAtFailure(true)
{
setWindowTitle(i18n("Krusader::Disk Usage"));
setAttribute(Qt::WA_DeleteOnClose);
baseDirectory = openDir;
QVBoxLayout *mainLayout = new QVBoxLayout;
setLayout(mainLayout);
QGridLayout *duGrid = new QGridLayout();
duGrid->setSpacing(6);
duGrid->setContentsMargins(11, 11, 11, 11);
QWidget *duTools = new QWidget(this);
QHBoxLayout *duHBox = new QHBoxLayout(duTools);
duHBox->setContentsMargins(0, 0, 0, 0);
duTools->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
btnNewSearch = new QToolButton(duTools);
btnNewSearch->setIcon(Icon("document-open"));
duHBox->addWidget(btnNewSearch);
btnNewSearch->setToolTip(i18n("Start new disk usage search"));
btnRefresh = new QToolButton(duTools);
btnRefresh->setIcon(Icon("view-refresh"));
duHBox->addWidget(btnRefresh);
btnRefresh->setToolTip(i18n("Refresh"));
btnDirUp = new QToolButton(duTools);
btnDirUp->setIcon(Icon("go-up"));
duHBox->addWidget(btnDirUp);
btnDirUp->setToolTip(i18n("Parent folder"));
QWidget *separatorWidget = new QWidget(duTools);
separatorWidget->setMinimumWidth(10);
duHBox->addWidget(separatorWidget);
btnLines = new QToolButton(duTools);
btnLines->setIcon(Icon("view-list-details"));
btnLines->setCheckable(true);
duHBox->addWidget(btnLines);
btnLines->setToolTip(i18n("Line view"));
btnDetailed = new QToolButton(duTools);
btnDetailed->setIcon(Icon("view-list-tree"));
btnDetailed->setCheckable(true);
duHBox->addWidget(btnDetailed);
btnDetailed->setToolTip(i18n("Detailed view"));
btnFilelight = new QToolButton(duTools);
btnFilelight->setIcon(Icon("kr_diskusage"));
btnFilelight->setCheckable(true);
duHBox->addWidget(btnFilelight);
btnFilelight->setToolTip(i18n("Filelight view"));
QWidget *spacerWidget = new QWidget(duTools);
duHBox->addWidget(spacerWidget);
QHBoxLayout *hboxlayout = new QHBoxLayout(spacerWidget);
QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
hboxlayout->addItem(spacer);
duGrid->addWidget(duTools, 0, 0);
diskUsage = new DiskUsage("DiskUsage", this);
duGrid->addWidget(diskUsage, 1, 0);
status = new KSqueezedTextLabel(this);
duGrid->addWidget(status, 2, 0);
mainLayout->addLayout(duGrid);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
mainLayout->addWidget(buttonBox);
connect(buttonBox, &QDialogButtonBox::rejected, this, &DiskUsageGUI::close);
connect(diskUsage, &DiskUsage::status, this, &DiskUsageGUI::slotStatus);
connect(diskUsage, &DiskUsage::viewChanged, this, &DiskUsageGUI::slotViewChanged);
connect(diskUsage, &DiskUsage::newSearch, this, &DiskUsageGUI::askDir);
connect(diskUsage, &DiskUsage::loadFinished, this, &DiskUsageGUI::slotLoadFinished);
connect(btnNewSearch, &QToolButton::clicked, this, &DiskUsageGUI::askDir);
connect(btnRefresh, &QToolButton::clicked, this, &DiskUsageGUI::slotLoadUsageInfo);
connect(btnDirUp, &QToolButton::clicked, diskUsage, &DiskUsage::dirUp);
connect(btnLines, &QToolButton::clicked, this, &DiskUsageGUI::slotSelectLinesView);
connect(btnDetailed, &QToolButton::clicked, this, &DiskUsageGUI::slotSelectListView);
connect(btnFilelight, &QToolButton::clicked, this, &DiskUsageGUI::slotSelectFilelightView);
KConfigGroup group(krConfig, "DiskUsage");
int view = group.readEntry("View", VIEW_LINES);
if (view < VIEW_LINES || view > VIEW_FILELIGHT)
view = VIEW_LINES;
diskUsage->setView(view);
sizeX = group.readEntry("Window Width", QFontMetrics(font()).width("W") * 70);
sizeY = group.readEntry("Window Height", QFontMetrics(font()).height() * 25);
resize(sizeX, sizeY);
if (group.readEntry("Window Maximized", false)) {
setWindowState(windowState() | Qt::WindowMaximized);
}
}
void DiskUsageGUI::askDirAndShow()
{
if (askDir()) {
show();
}
}
void DiskUsageGUI::slotLoadFinished(bool result)
{
if (exitAtFailure && !result) {
close();
} else {
exitAtFailure = false;
}
}
void DiskUsageGUI::enableButtons(bool isOn)
{
btnNewSearch->setEnabled(isOn);
btnRefresh->setEnabled(isOn);
btnDirUp->setEnabled(isOn);
btnLines->setEnabled(isOn);
btnDetailed->setEnabled(isOn);
btnFilelight->setEnabled(isOn);
}
void DiskUsageGUI::resizeEvent(QResizeEvent *e)
{
if (!isMaximized()) {
sizeX = e->size().width();
sizeY = e->size().height();
}
QDialog::resizeEvent(e);
}
void DiskUsageGUI::closeEvent(QCloseEvent *event)
{
KConfigGroup group(krConfig, "DiskUsage");
group.writeEntry("Window Width", sizeX);
group.writeEntry("Window Height", sizeY);
group.writeEntry("Window Maximized", isMaximized());
group.writeEntry("View", diskUsage->getActiveView());
event->accept();
}
void DiskUsageGUI::slotLoadUsageInfo()
{
diskUsage->load(baseDirectory);
}
void DiskUsageGUI::slotStatus(QString stat)
{
status->setText(stat);
}
void DiskUsageGUI::slotViewChanged(int view)
{
if (view == VIEW_LOADER) {
enableButtons(false);
return;
}
enableButtons(true);
btnLines->setChecked(false);
btnDetailed->setChecked(false);
btnFilelight->setChecked(false);
switch (view) {
case VIEW_LINES:
btnLines->setChecked(true);
break;
case VIEW_DETAILED:
btnDetailed->setChecked(true);
break;
case VIEW_FILELIGHT:
btnFilelight->setChecked(true);
break;
case VIEW_LOADER:
break;
}
}
bool DiskUsageGUI::askDir()
{
// ask the user for the copy destX
const QUrl newDir =
KChooseDir::getDir(i18n("Viewing the usage of folder:"), baseDirectory, baseDirectory);
if (newDir.isEmpty())
return false;
baseDirectory = newDir;
- QTimer::singleShot(0, this, SLOT(slotLoadUsageInfo()));
+ QTimer::singleShot(0, this, &DiskUsageGUI::slotLoadUsageInfo);
return true;
}
diff --git a/krusader/DiskUsage/dulines.cpp b/krusader/DiskUsage/dulines.cpp
index 85ba4948..62e80978 100644
--- a/krusader/DiskUsage/dulines.cpp
+++ b/krusader/DiskUsage/dulines.cpp
@@ -1,534 +1,534 @@
/*****************************************************************************
* Copyright (C) 2004 Csaba Karai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "dulines.h"
#include "../icon.h"
#include "../krglobal.h"
#include "../FileSystem/krpermhandler.h"
// QtCore
#include
// QtGui
#include
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
class DULinesItemDelegate : public QItemDelegate
{
public:
explicit DULinesItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {}
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE {
QItemDelegate::paint(painter, option, index);
QVariant value = index.data(Qt::UserRole);
if (value.isValid()) {
QString text = value.toString();
value = index.data(Qt::DisplayRole);
QString display;
if (value.isValid())
display = value.toString();
QSize iconSize;
value = index.data(Qt::DecorationRole);
if (value.isValid())
iconSize = qvariant_cast(value).actualSize(option.decorationSize);
painter->save();
painter->setClipRect(option.rect);
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
cg = QPalette::Inactive;
if (option.state & QStyle::State_Selected) {
painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
} else {
painter->setPen(option.palette.color(cg, QPalette::Text));
}
QFont fnt = option.font;
fnt.setItalic(true);
painter->setFont(fnt);
QFontMetrics fm(fnt);
QString renderedText = text;
int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
int pos = 3 * textMargin + option.fontMetrics.width(display) + iconSize.width();
bool truncd = false;
QRect rct = option.rect;
if (rct.width() > pos) {
rct.setX(rct.x() + pos);
if (fm.width(renderedText) > rct.width()) {
truncd = true;
int points = fm.width("...");
while (!renderedText.isEmpty() && (fm.width(renderedText) + points > rct.width()))
renderedText.truncate(renderedText.length() - 1);
renderedText += "...";
}
painter->drawText(rct, Qt::AlignLeft, renderedText);
} else
truncd = true;
if (truncd)
((QAbstractItemModel *)index.model())->setData(index, QVariant(display + " " + text), Qt::ToolTipRole);
else
((QAbstractItemModel *)index.model())->setData(index, QVariant(), Qt::ToolTipRole);
painter->restore();
}
}
};
class DULinesItem : public QTreeWidgetItem
{
public:
DULinesItem(DiskUsage *diskUsageIn, File *fileItem, QTreeWidget * parent, QString label1,
QString label2, QString label3) : QTreeWidgetItem(parent),
diskUsage(diskUsageIn), file(fileItem) {
setText(0, label1);
setText(1, label2);
setText(2, label3);
setTextAlignment(1, Qt::AlignRight);
}
DULinesItem(DiskUsage *diskUsageIn, File *fileItem, QTreeWidget * parent, QTreeWidgetItem * after,
QString label1, QString label2, QString label3) : QTreeWidgetItem(parent, after),
diskUsage(diskUsageIn), file(fileItem) {
setText(0, label1);
setText(1, label2);
setText(2, label3);
setTextAlignment(1, Qt::AlignRight);
}
virtual bool operator<(const QTreeWidgetItem &other) const Q_DECL_OVERRIDE {
int column = treeWidget() ? treeWidget()->sortColumn() : 0;
if (text(0) == "..")
return true;
const DULinesItem *compWith = dynamic_cast< const DULinesItem * >(&other);
if (compWith == 0)
return false;
switch (column) {
case 0:
case 1:
return file->size() > compWith->file->size();
default:
return text(column) < other.text(column);
}
}
inline File * getFile() {
return file;
}
private:
DiskUsage *diskUsage;
File *file;
};
DULines::DULines(DiskUsage *usage)
: KrTreeWidget(usage), diskUsage(usage), refreshNeeded(false), started(false)
{
setItemDelegate(itemDelegate = new DULinesItemDelegate());
setAllColumnsShowFocus(true);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setIndentation(10);
int defaultSize = QFontMetrics(font()).width("W");
QStringList labels;
labels << i18n("Line View");
labels << i18n("Percent");
labels << i18n("Name");
setHeaderLabels(labels);
header()->setSectionResizeMode(QHeaderView::Interactive);
KConfigGroup group(krConfig, diskUsage->getConfigGroup());
showFileSize = group.readEntry("L Show File Size", true);
if (group.hasKey("L State"))
header()->restoreState(group.readEntry("L State", QByteArray()));
else {
setColumnWidth(0, defaultSize * 20);
setColumnWidth(1, defaultSize * 6);
setColumnWidth(2, defaultSize * 20);
}
setStretchingColumn(0);
header()->setSortIndicatorShown(true);
sortItems(1, Qt::AscendingOrder);
// toolTip = new DULinesToolTip( diskUsage, viewport(), this );
connect(diskUsage, &DiskUsage::enteringDirectory, this, &DULines::slotDirChanged);
connect(diskUsage, &DiskUsage::clearing, this, &DULines::clear);
connect(header(), &QHeaderView::sectionResized, this, &DULines::sectionResized);
connect(this, &DULines::itemRightClicked, this, &DULines::slotRightClicked);
connect(diskUsage, &DiskUsage::changed, this, &DULines::slotChanged);
connect(diskUsage, &DiskUsage::deleted, this, &DULines::slotDeleted);
started = true;
}
DULines::~DULines()
{
KConfigGroup group(krConfig, diskUsage->getConfigGroup());
group.writeEntry("L State", header()->saveState());
delete itemDelegate;
}
bool DULines::event(QEvent * event)
{
switch (event->type()) {
case QEvent::ToolTip: {
QHelpEvent *he = static_cast(event);
if (viewport()) {
QPoint pos = viewport()->mapFromGlobal(he->globalPos());
QTreeWidgetItem * item = itemAt(pos);
int column = columnAt(pos.x());
if (item && column == 1) {
File *fileItem = ((DULinesItem *)item)->getFile();
QToolTip::showText(he->globalPos(), diskUsage->getToolTip(fileItem), this);
return true;
}
}
}
break;
default:
break;
}
return KrTreeWidget::event(event);
}
void DULines::slotDirChanged(Directory *dirEntry)
{
clear();
QTreeWidgetItem * lastItem = 0;
if (!(dirEntry->parent() == 0)) {
lastItem = new QTreeWidgetItem(this);
lastItem->setText(0, "..");
lastItem->setIcon(0, Icon("go-up"));
lastItem->setFlags(lastItem->flags() & (~Qt::ItemIsSelectable));
}
int maxPercent = -1;
for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) {
File *item = *it;
if (!item->isExcluded() && item->intPercent() > maxPercent)
maxPercent = item->intPercent();
}
for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) {
File *item = *it;
QString fileName = item->name();
if (lastItem == 0)
lastItem = new DULinesItem(diskUsage, item, this, "", item->percent() + " ", fileName);
else
lastItem = new DULinesItem(diskUsage, item, this, lastItem, "", item->percent() + " ", fileName);
if (item->isExcluded())
lastItem->setHidden(true);
int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
lastItem->setIcon(2, diskUsage->getIcon(item->mime()));
lastItem->setData(0, Qt::DecorationRole, createPixmap(item->intPercent(), maxPercent, header()->sectionSize(0) - 2 * textMargin));
if (showFileSize)
lastItem->setData(2, Qt::UserRole, " [" + KIO::convertSize(item->size()) + ']');
QSize size = lastItem->sizeHint(0);
size.setWidth(16);
lastItem->setSizeHint(0, size);
}
if (topLevelItemCount() > 0) {
setCurrentItem(topLevelItem(0));
}
}
QPixmap DULines::createPixmap(int percent, int maxPercent, int maxWidth)
{
if (percent < 0 || percent > maxPercent || maxWidth < 2 || maxPercent == 0)
return QPixmap();
maxWidth -= 2;
int actualWidth = maxWidth * percent / maxPercent;
if (actualWidth == 0)
return QPixmap();
QPen pen;
pen.setColor(Qt::black);
QPainter painter;
int size = QFontMetrics(font()).height() - 2;
QRect rect(0, 0, actualWidth, size);
QRect frameRect(0, 0, actualWidth - 1, size - 1);
QPixmap pixmap(rect.width(), rect.height());
painter.begin(&pixmap);
painter.setPen(pen);
for (int i = 1; i < actualWidth - 1; i++) {
int color = (511 * i / (maxWidth - 1));
if (color < 256)
pen.setColor(QColor(255 - color, 255, 0));
else
pen.setColor(QColor(color - 256, 511 - color, 0));
painter.setPen(pen);
painter.drawLine(i, 1, i, size - 1);
}
pen.setColor(Qt::black);
painter.setPen(pen);
if (actualWidth != 1)
painter.drawRect(frameRect);
else
painter.drawLine(0, 0, 0, size);
painter.end();
pixmap.detach();
return pixmap;
}
void DULines::resizeEvent(QResizeEvent * re)
{
KrTreeWidget::resizeEvent(re);
if (started && (re->oldSize() != re->size()))
sectionResized(0);
}
void DULines::sectionResized(int column)
{
if (topLevelItemCount() == 0 || column != 0)
return;
Directory * currentDir = diskUsage->getCurrentDir();
if (currentDir == 0)
return;
int maxPercent = -1;
for (Iterator it = currentDir->iterator(); it != currentDir->end(); ++it) {
File *item = *it;
if (!item->isExcluded() && item->intPercent() > maxPercent)
maxPercent = item->intPercent();
}
QTreeWidgetItemIterator it2(this);
while (*it2) {
QTreeWidgetItem *lvitem = *it2;
if (lvitem->text(0) != "..") {
DULinesItem *duItem = dynamic_cast< DULinesItem *>(lvitem);
if (duItem) {
int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
duItem->setData(0, Qt::DecorationRole, createPixmap(duItem->getFile()->intPercent(), maxPercent, header()->sectionSize(0) - 2 * textMargin));
QSize size = duItem->sizeHint(0);
size.setWidth(16);
duItem->setSizeHint(0, size);
}
}
it2++;
}
}
bool DULines::doubleClicked(QTreeWidgetItem * item)
{
if (item) {
if (item->text(0) != "..") {
File *fileItem = ((DULinesItem *)item)->getFile();
if (fileItem->isDir())
diskUsage->changeDirectory(dynamic_cast(fileItem));
return true;
} else {
Directory *upDir = (Directory *)diskUsage->getCurrentDir()->parent();
if (upDir)
diskUsage->changeDirectory(upDir);
return true;
}
}
return false;
}
void DULines::mouseDoubleClickEvent(QMouseEvent * e)
{
if (e || e->button() == Qt::LeftButton) {
QPoint vp = viewport()->mapFromGlobal(e->globalPos());
QTreeWidgetItem * item = itemAt(vp);
if (doubleClicked(item))
return;
}
KrTreeWidget::mouseDoubleClickEvent(e);
}
void DULines::keyPressEvent(QKeyEvent *e)
{
switch (e->key()) {
case Qt::Key_Return :
case Qt::Key_Enter :
if (doubleClicked(currentItem()))
return;
break;
case Qt::Key_Left :
case Qt::Key_Right :
case Qt::Key_Up :
case Qt::Key_Down :
if (e->modifiers() == Qt::ShiftModifier) {
e->ignore();
return;
}
break;
case Qt::Key_Delete :
e->ignore();
return;
}
KrTreeWidget::keyPressEvent(e);
}
void DULines::slotRightClicked(QTreeWidgetItem *item, const QPoint &pos)
{
File * file = 0;
if (item && item->text(0) != "..")
file = ((DULinesItem *)item)->getFile();
QMenu linesPopup;
QAction *act = linesPopup.addAction(i18n("Show file sizes"), this, SLOT(slotShowFileSizes()));
act->setChecked(showFileSize);
diskUsage->rightClickMenu(pos, file, &linesPopup, i18n("Lines"));
}
void DULines::slotShowFileSizes()
{
showFileSize = !showFileSize;
slotDirChanged(diskUsage->getCurrentDir());
}
File * DULines::getCurrentFile()
{
QTreeWidgetItem *item = currentItem();
if (item == 0 || item->text(0) == "..")
return 0;
return ((DULinesItem *)item)->getFile();
}
void DULines::slotChanged(File * item)
{
QTreeWidgetItemIterator it(this);
while (*it) {
QTreeWidgetItem *lvitem = *it;
it++;
if (lvitem->text(0) != "..") {
DULinesItem *duItem = (DULinesItem *)(lvitem);
if (duItem->getFile() == item) {
setSortingEnabled(false);
duItem->setHidden(item->isExcluded());
duItem->setText(1, item->percent());
if (!refreshNeeded) {
refreshNeeded = true;
- QTimer::singleShot(0, this, SLOT(slotRefresh()));
+ QTimer::singleShot(0, this, &DULines::slotRefresh);
}
break;
}
}
}
}
void DULines::slotDeleted(File * item)
{
QTreeWidgetItemIterator it(this);
while (*it) {
QTreeWidgetItem *lvitem = *it;
it++;
if (lvitem->text(0) != "..") {
DULinesItem *duItem = (DULinesItem *)(lvitem);
if (duItem->getFile() == item) {
delete duItem;
break;
}
}
}
}
void DULines::slotRefresh()
{
if (refreshNeeded) {
refreshNeeded = false;
setSortingEnabled(true);
sortItems(1, Qt::AscendingOrder);
}
}
diff --git a/krusader/FileSystem/sizecalculator.cpp b/krusader/FileSystem/sizecalculator.cpp
index 76191d15..611e7823 100644
--- a/krusader/FileSystem/sizecalculator.cpp
+++ b/krusader/FileSystem/sizecalculator.cpp
@@ -1,184 +1,184 @@
/*****************************************************************************
* Copyright (C) 2017-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "sizecalculator.h"
// QtCore
#include
#include
#include
#include "fileitem.h"
#include "virtualfilesystem.h"
SizeCalculator::SizeCalculator(const QList &urls)
: QObject(nullptr), m_urls(urls), m_nextUrls(urls), m_totalSize(0), m_totalFiles(0),
m_totalDirs(0), m_canceled(false), m_directorySizeJob(nullptr)
{
- QTimer::singleShot(0, this, SLOT(start()));
+ QTimer::singleShot(0, this, &SizeCalculator::start);
}
SizeCalculator::~SizeCalculator()
{
if (m_directorySizeJob)
m_directorySizeJob->kill();
}
void SizeCalculator::start()
{
emit started();
nextUrl();
}
void SizeCalculator::add(const QUrl &url)
{
m_urls.append(url);
m_nextUrls.append(url);
emitProgress();
}
KIO::filesize_t SizeCalculator::totalSize() const
{
return m_totalSize + (m_directorySizeJob ? m_directorySizeJob->totalSize() : 0);
}
unsigned long SizeCalculator::totalFiles() const
{
return m_totalFiles + (m_directorySizeJob ? m_directorySizeJob->totalFiles() : 0);
}
unsigned long SizeCalculator::totalDirs() const
{
return m_totalDirs + (m_directorySizeJob ? m_directorySizeJob->totalSubdirs() : 0);
}
void SizeCalculator::cancel()
{
m_canceled = true;
if (m_directorySizeJob)
m_directorySizeJob->kill();
done();
}
void SizeCalculator::nextUrl()
{
if (m_canceled)
return;
emitProgress();
if (!m_currentUrl.isEmpty())
emit calculated(m_currentUrl, m_currentUrlSize);
m_currentUrlSize = 0;
if (m_nextUrls.isEmpty()) {
done();
return;
}
m_currentUrl = m_nextUrls.takeFirst();
if (m_currentUrl.scheme() == "virt") {
// calculate size of all files/directories in this virtual directory
VirtualFileSystem *fs = new VirtualFileSystem();
if (!fs->scanDir(m_currentUrl)) {
qWarning() << "cannot scan virtual FS, URL=" << m_currentUrl.toDisplayString();
nextUrl();
return;
}
for (FileItem *file : fs->fileItems())
m_nextSubUrls << file->getUrl();
delete fs;
} else {
m_nextSubUrls << m_currentUrl;
}
nextSubUrl();
}
void SizeCalculator::nextSubUrl()
{
if (m_canceled)
return;
if (m_nextSubUrls.isEmpty()) {
nextUrl();
return;
}
const QUrl url = m_nextSubUrls.takeFirst();
KIO::StatJob *statJob = KIO::stat(url, KIO::HideProgressInfo);
connect(statJob, &KIO::Job::result, this, &SizeCalculator::slotStatResult);
}
void SizeCalculator::slotStatResult(KJob *job)
{
if (m_canceled)
return;
if (job->error()) {
qWarning() << "stat job failed, error=" << job->error() << "; error string=" << job->errorString();
nextSubUrl();
return;
}
const KIO::StatJob *statJob = static_cast(job);
const QUrl url = statJob->url();
const KFileItem kfi(statJob->statResult(), url, true);
if (kfi.isFile() || kfi.isLink()) {
m_totalFiles++;
m_totalSize += kfi.size();
m_currentUrlSize += kfi.size();
nextSubUrl();
return;
}
// URL should be a directory, we are always counting the directory itself
m_totalDirs++;
m_directorySizeJob = KIO::directorySize(url);
connect(m_directorySizeJob.data(), &KIO::Job::result, this, &SizeCalculator::slotDirectorySizeResult);
}
void SizeCalculator::slotDirectorySizeResult(KJob *)
{
if (!m_directorySizeJob->error()) {
m_totalSize += m_directorySizeJob->totalSize();
// do not count filesystem size of empty directories for this current directory
m_currentUrlSize +=
m_directorySizeJob->totalFiles() == 0 ? 0 : m_directorySizeJob->totalSize();
m_totalFiles += m_directorySizeJob->totalFiles();
m_totalDirs += m_directorySizeJob->totalSubdirs();
}
m_directorySizeJob = 0;
nextSubUrl();
}
void SizeCalculator::done()
{
emit finished(m_canceled);
deleteLater();
}
void SizeCalculator::emitProgress()
{
emit progressChanged((m_urls.length() - (float)m_nextUrls.length()) / m_urls.length() * 100);
}
diff --git a/krusader/Filter/generalfilter.cpp b/krusader/Filter/generalfilter.cpp
index 717be545..3afcb6ef 100644
--- a/krusader/Filter/generalfilter.cpp
+++ b/krusader/Filter/generalfilter.cpp
@@ -1,666 +1,666 @@
/*****************************************************************************
* Copyright (C) 2003 Shie Erlich *
* Copyright (C) 2003 Rafi Yanai *
* Copyright (C) 2003 Csaba Karai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "generalfilter.h"
#include "filtertabs.h"
#include "../krglobal.h"
#include "../krservices.h"
#include "../FileSystem/filesystem.h"
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct {
const char *description;
const char *regExp;
int cursorAdjustment;
} term;
static const term items[] = {
{ I18N_NOOP("Any Character"), ".", 0 },
{ I18N_NOOP("Start of Line"), "^", 0 },
{ I18N_NOOP("End of Line"), "$", 0 },
{ I18N_NOOP("Set of Characters"), "[]", -1 },
{ I18N_NOOP("Repeats, Zero or More Times"), "*", 0 },
{ I18N_NOOP("Repeats, One or More Times"), "+", 0 },
{ I18N_NOOP("Optional"), "?", 0 },
{ I18N_NOOP("Escape"), "\\", 0 },
{ I18N_NOOP("TAB"), "\\t", 0 },
{ I18N_NOOP("Newline"), "\\n", 0 },
{ I18N_NOOP("Carriage Return"), "\\r", 0 },
{ I18N_NOOP("White Space"), "\\s", 0 },
{ I18N_NOOP("Digit"), "\\d", 0 },
};
class RegExpAction : public QAction
{
public:
RegExpAction(QObject *parent, const QString &text, const QString ®Exp, int cursor)
: QAction(text, parent), mText(text), mRegExp(regExp), mCursor(cursor) {
}
QString text() const {
return mText;
}
QString regExp() const {
return mRegExp;
}
int cursor() const {
return mCursor;
}
private:
QString mText;
QString mRegExp;
int mCursor;
};
GeneralFilter::GeneralFilter(FilterTabs *tabs, int properties, QWidget *parent,
QStringList extraOptions) :
QWidget(parent),
profileManager(0), fltTabs(tabs)
{
QGridLayout *filterLayout = new QGridLayout(this);
filterLayout->setSpacing(6);
filterLayout->setContentsMargins(11, 11, 11, 11);
this->properties = properties;
// Options for name filtering
QGroupBox *nameGroup = new QGroupBox(this);
nameGroup->setTitle(i18n("File Name"));
QGridLayout *nameGroupLayout = new QGridLayout(nameGroup);
nameGroupLayout->setAlignment(Qt::AlignTop);
nameGroupLayout->setSpacing(6);
nameGroupLayout->setContentsMargins(11, 11, 11, 11);
searchForCase = new QCheckBox(nameGroup);
searchForCase->setText(i18n("&Case sensitive"));
searchForCase->setChecked(false);
nameGroupLayout->addWidget(searchForCase, 1, 2);
QLabel *searchForLabel = new QLabel(nameGroup);
searchForLabel->setText(i18n("Search &for:"));
nameGroupLayout->addWidget(searchForLabel, 0, 0);
searchFor = new KHistoryComboBox(false, nameGroup/*, "searchFor"*/);
QSizePolicy searchForPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
searchForPolicy.setHeightForWidth(searchFor->sizePolicy().hasHeightForWidth());
searchFor->setSizePolicy(searchForPolicy);
searchFor->setEditable(true);
searchFor->setDuplicatesEnabled(false);
searchFor->setMaxCount(25);
searchFor->setMinimumContentsLength(10);
searchForLabel->setBuddy(searchFor);
nameGroupLayout->addWidget(searchFor, 0, 1, 1, 2);
const QString s = ""
+ i18n("The filename filtering criteria is defined here.
"
"You can make use of wildcards. Multiple patterns are separated by "
"space (means logical OR) and patterns are excluded from the search "
"using the pipe symbol.
"
"If the pattern is ended with a slash (*pattern*/
), "
"that means that pattern relates to recursive search of folders."
"
pattern
- means to search those files/folders "
"that name is pattern
, recursive search goes through all "
"subfolders independently of the value of pattern
"
"pattern/
- means to search all files/folders, but "
"recursive search goes through/excludes the folders that name is "
"pattern
"
"It is allowed to use quotation marks for names that contain space."
" Filter \"Program Files\"
searches out those "
"files/folders that name is Program Files
.
"
"Examples:
"
"*.o
"
"*.h *.c\?\?
"
"*.cpp *.h | *.moc.cpp
"
"* | .svn/ .git/
"
"Note: the search term 'text
' is equivalent to "
"'*text*
'.
");
searchFor->setWhatsThis(s);
searchForLabel->setWhatsThis(s);
QLabel *searchType = new QLabel(nameGroup);
searchType->setText(i18n("&Of type:"));
nameGroupLayout->addWidget(searchType, 1, 0);
ofType = new KComboBox(false, nameGroup);
ofType->setObjectName("ofType");
QSizePolicy ofTypePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
ofTypePolicy.setHeightForWidth(ofType->sizePolicy().hasHeightForWidth());
ofType->setSizePolicy(ofTypePolicy);
ofType->setEditable(false);
searchType->setBuddy(ofType);
ofType->addItem(i18n("All Files"));
ofType->addItem(i18n("Archives"));
ofType->addItem(i18n("Folders"));
ofType->addItem(i18n("Image Files"));
ofType->addItem(i18n("Text Files"));
ofType->addItem(i18n("Video Files"));
ofType->addItem(i18n("Audio Files"));
connect(ofType, QOverload::of(&KComboBox::currentIndexChanged), this, &GeneralFilter::slotDisable);
nameGroupLayout->addWidget(ofType, 1, 1);
filterLayout->addWidget(nameGroup, 0, 0);
middleLayout = new QHBoxLayout();
middleLayout->setSpacing(6);
middleLayout->setContentsMargins(0, 0, 0, 0);
if (properties & FilterTabs::HasProfileHandler) {
// The profile handler
QGroupBox *profileHandler = new QGroupBox(this);
profileHandler->setTitle(i18n("&Profile handler"));
QGridLayout *profileLayout = new QGridLayout(profileHandler);
profileLayout->setAlignment(Qt::AlignTop);
profileLayout->setSpacing(6);
profileLayout->setContentsMargins(11, 11, 11, 11);
profileListBox = new KrListWidget(profileHandler);
profileLayout->addWidget(profileListBox, 0, 0, 4, 1);
profileAddBtn = new QPushButton(profileHandler);
KStandardGuiItem::assign(profileAddBtn, KStandardGuiItem::Add);
profileLayout->addWidget(profileAddBtn, 0, 1);
profileLoadBtn = new QPushButton(i18n("&Load"), profileHandler);
profileLoadBtn->setEnabled(false);
profileLayout->addWidget(profileLoadBtn, 1, 1);
profileOverwriteBtn = new QPushButton(profileHandler);
profileOverwriteBtn->setEnabled(false);
KStandardGuiItem::assign(profileOverwriteBtn, KStandardGuiItem::Overwrite);
profileLayout->addWidget(profileOverwriteBtn, 2, 1);
profileRemoveBtn = new QPushButton(profileHandler);
profileRemoveBtn->setEnabled(false);
KStandardGuiItem::assign(profileRemoveBtn, KStandardGuiItem::Remove);
profileLayout->addWidget(profileRemoveBtn, 3, 1);
profileManager = new ProfileManager("SelectionProfile", this);
profileManager->hide();
middleLayout->addWidget(profileHandler);
refreshProfileListBox();
}
if (properties & FilterTabs::HasSearchIn) {
// Options for search in
QGroupBox *searchGroupBox = new QGroupBox(i18n("Searc&h in"), this);
QGridLayout *searchLayout = new QGridLayout(searchGroupBox);
searchLayout->setAlignment(Qt::AlignTop);
searchLayout->setSpacing(6);
searchLayout->setContentsMargins(11, 11, 11, 11);
searchIn = new KURLListRequester(KURLListRequester::RequestDirs, searchGroupBox);
searchLayout->addWidget(searchIn, 0, 0);
connect(searchIn, &KURLListRequester::changed, this, &GeneralFilter::slotDisable);
middleLayout->addWidget(searchGroupBox);
}
if (properties & FilterTabs::HasDontSearchIn) {
// Options for don't search in
QGroupBox *searchGroupBox = new QGroupBox(i18n("&Do not search in"), this);
QGridLayout *searchLayout = new QGridLayout(searchGroupBox);
searchLayout->setAlignment(Qt::AlignTop);
searchLayout->setSpacing(6);
searchLayout->setContentsMargins(11, 11, 11, 11);
dontSearchIn = new KURLListRequester(KURLListRequester::RequestDirs, searchGroupBox);
searchLayout->addWidget(dontSearchIn, 0, 0, 1, 2);
if (properties & FilterTabs::HasRecurseOptions) {
KConfigGroup group(krConfig, "Search");
useExcludeFolderNames = createExcludeCheckBox(group);
searchLayout->addWidget(useExcludeFolderNames, 1, 0, 1, 1);
excludeFolderNames = createExcludeComboBox(group);
searchLayout->addWidget(excludeFolderNames, 1, 1, 1, 1);
if (!useExcludeFolderNames->isChecked()) {
excludeFolderNames->setDisabled(true);
}
connect(useExcludeFolderNames, &QCheckBox::toggled, excludeFolderNames, &KHistoryComboBox::setEnabled);
}
middleLayout->addWidget(searchGroupBox);
}
filterLayout->addLayout(middleLayout, 1, 0);
// Options for containing text
QGroupBox *containsGroup = new QGroupBox(this);
containsGroup->setTitle(i18n("Containing text"));
QGridLayout *containsLayout = new QGridLayout(containsGroup);
containsLayout->setAlignment(Qt::AlignTop);
containsLayout->setSpacing(6);
containsLayout->setContentsMargins(11, 11, 11, 11);
QHBoxLayout *containsTextLayout = new QHBoxLayout();
containsTextLayout->setSpacing(6);
containsTextLayout->setContentsMargins(0, 0, 0, 0);
containsLabel = new QLabel(containsGroup);
QSizePolicy containsLabelPolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
containsLabelPolicy.setHeightForWidth(containsLabel->sizePolicy().hasHeightForWidth());
containsLabel->setSizePolicy(containsLabelPolicy);
containsLabel->setText(i18n("&Text:"));
containsTextLayout->addWidget(containsLabel);
containsText = new KHistoryComboBox(false, containsGroup/*, "containsText"*/);
QSizePolicy containsTextPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
containsTextPolicy.setHeightForWidth(containsText->sizePolicy().hasHeightForWidth());
containsText->setSizePolicy(containsTextPolicy);
containsText->setDuplicatesEnabled(false);
containsText->setMaxCount(25);
containsText->setMinimumContentsLength(10);
containsTextLayout->addWidget(containsText);
containsLabel->setBuddy(containsText);
containsRegExp = new QToolButton(containsGroup);
containsRegExp->setPopupMode(QToolButton::MenuButtonPopup);
containsRegExp->setCheckable(true);
containsRegExp->setText(i18n("RegExp"));
// Populate the popup menu.
QMenu *patterns = new QMenu(containsRegExp);
for (int i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++) {
patterns->addAction(new RegExpAction(patterns, i18n(items[i].description),
items[i].regExp, items[i].cursorAdjustment));
}
connect(containsRegExp, &QToolButton::toggled, this, &GeneralFilter::slotDisable);
connect(containsRegExp, &QToolButton::triggered, this, &GeneralFilter::slotRegExpTriggered);
containsRegExp->setMenu(patterns);
patterns->setEnabled(false);
containsTextLayout->addWidget(containsRegExp);
containsLayout->addLayout(containsTextLayout, 0, 0);
QHBoxLayout *containsCbsLayout = new QHBoxLayout();
containsCbsLayout->setSpacing(6);
containsCbsLayout->setContentsMargins(0, 0, 0, 0);
encLabel = new QLabel(i18n("Encoding:"), containsGroup);
containsCbsLayout->addWidget(encLabel);
contentEncoding = new KComboBox(containsGroup);
contentEncoding->setEditable(false);
contentEncoding->addItem(i18nc("Default encoding", "Default"));
contentEncoding->addItems(KCharsets::charsets()->descriptiveEncodingNames());
containsCbsLayout->addWidget(contentEncoding);
QSpacerItem* cbSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
containsCbsLayout->addItem(cbSpacer);
containsWholeWord = new QCheckBox(containsGroup);
QSizePolicy containsWholeWordPolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
containsWholeWordPolicy.setHeightForWidth(containsWholeWord->sizePolicy().hasHeightForWidth());
containsWholeWord->setSizePolicy(containsWholeWordPolicy);
containsWholeWord->setText(i18n("&Match whole word only"));
containsWholeWord->setChecked(false);
containsCbsLayout->addWidget(containsWholeWord);
containsTextCase = new QCheckBox(containsGroup);
QSizePolicy containsTextCasePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
containsTextCasePolicy.setHeightForWidth(containsTextCase->sizePolicy().hasHeightForWidth());
containsTextCase->setSizePolicy(containsTextCasePolicy);
containsTextCase->setText(i18n("Cas&e sensitive"));
containsTextCase->setChecked(true);
containsCbsLayout->addWidget(containsTextCase);
containsLayout->addLayout(containsCbsLayout, 1, 0);
filterLayout->addWidget(containsGroup, 2, 0);
QHBoxLayout *recurseLayout = new QHBoxLayout();
recurseLayout->setSpacing(6);
recurseLayout->setContentsMargins(0, 0, 0, 0);
QSpacerItem* recurseSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
recurseLayout->addItem(recurseSpacer);
if (properties & FilterTabs::HasRecurseOptions) {
// Options for recursive searching
searchInDirs = new QCheckBox(this);
searchInDirs->setText(i18n("Search in s&ub folders"));
searchInDirs->setChecked(true);
recurseLayout->addWidget(searchInDirs);
searchInArchives = new QCheckBox(this);
searchInArchives->setText(i18n("Search in arch&ives"));
recurseLayout->addWidget(searchInArchives);
followLinks = new QCheckBox(this);
followLinks->setText(i18n("Follow &links"));
recurseLayout->addWidget(followLinks);
}
filterLayout->addLayout(recurseLayout, 3, 0);
for(int i = 0; i < extraOptions.length(); i++) {
QCheckBox *option = new QCheckBox(this);
option->setText(extraOptions[i]);
recurseLayout->addWidget(option);
this->extraOptions.insert(extraOptions[i], option);
}
// Connection table
if (properties & FilterTabs::HasProfileHandler) {
connect(profileAddBtn, &QPushButton::clicked, this, &GeneralFilter::slotAddBtnClicked);
connect(profileLoadBtn, &QPushButton::clicked, this, &GeneralFilter::slotLoadBtnClicked);
connect(profileOverwriteBtn, &QPushButton::clicked, this, &GeneralFilter::slotOverwriteBtnClicked);
connect(profileRemoveBtn, &QPushButton::clicked, this, &GeneralFilter::slotRemoveBtnClicked);
connect(profileListBox, &KrListWidget::itemDoubleClicked, this, &GeneralFilter::slotProfileDoubleClicked);
connect(profileManager, &ProfileManager::loadFromProfile, fltTabs, &FilterTabs::loadFromProfile);
connect(profileManager, &ProfileManager::saveToProfile, fltTabs, &FilterTabs::saveToProfile);
}
- connect(searchFor, SIGNAL(activated(QString)), searchFor, SLOT(addToHistory(QString)));
- connect(containsText, SIGNAL(activated(QString)), containsText, SLOT(addToHistory(QString)));
+ connect(searchFor, QOverload::of(&KHistoryComboBox::activated), searchFor, &KHistoryComboBox::addToHistory);
+ connect(containsText, QOverload::of(&KHistoryComboBox::activated), containsText, &KHistoryComboBox::addToHistory);
// load the completion and history lists
// ==> search for
KConfigGroup group(krConfig, "Search");
QStringList list = group.readEntry("SearchFor Completion", QStringList());
searchFor->completionObject()->setItems(list);
list = group.readEntry("SearchFor History", QStringList());
searchFor->setHistoryItems(list);
// ==> grep
list = group.readEntry("ContainsText Completion", QStringList());
containsText->completionObject()->setItems(list);
list = group.readEntry("ContainsText History", QStringList());
containsText->setHistoryItems(list);
setTabOrder(searchFor, containsText); // search for -> content
setTabOrder(containsText, searchType); // content -> search type
slotDisable();
}
GeneralFilter::~GeneralFilter()
{
// save the history combos
// ==> search for
QStringList list = searchFor->completionObject()->items();
KConfigGroup group(krConfig, "Search");
group.writeEntry("SearchFor Completion", list);
list = searchFor->historyItems();
group.writeEntry("SearchFor History", list);
// ==> grep text
list = containsText->completionObject()->items();
group.writeEntry("ContainsText Completion", list);
list = containsText->historyItems();
group.writeEntry("ContainsText History", list);
if ((properties & FilterTabs::HasDontSearchIn) && (properties & FilterTabs::HasRecurseOptions)) {
list = excludeFolderNames->historyItems();
group.writeEntry("ExcludeFolderNamesHistory", list);
group.writeEntry("ExcludeFolderNames", excludeFolderNames->currentText());
group.writeEntry("ExcludeFolderNamesUse", static_cast(useExcludeFolderNames->checkState()));
}
krConfig->sync();
}
bool GeneralFilter::isExtraOptionChecked(QString name)
{
QCheckBox *option = extraOptions[name];
return option ? option->isChecked() : false;
}
void GeneralFilter::checkExtraOption(QString name, bool check)
{
QCheckBox *option = extraOptions[name];
if (option)
option->setChecked(check);
}
void GeneralFilter::queryAccepted()
{
searchFor->addToHistory(searchFor->currentText());
containsText->addToHistory(containsText->currentText());
if ((properties & FilterTabs::HasDontSearchIn) && (properties & FilterTabs::HasRecurseOptions)) {
excludeFolderNames->addToHistory(excludeFolderNames->currentText());
}
}
void GeneralFilter::refreshProfileListBox()
{
profileListBox->clear();
profileListBox->addItems(ProfileManager::availableProfiles("SelectionProfile"));
if (profileListBox->count() != 0) {
profileLoadBtn->setEnabled(true);
profileOverwriteBtn->setEnabled(true);
profileRemoveBtn->setEnabled(true);
} else {
profileLoadBtn->setEnabled(false);
profileOverwriteBtn->setEnabled(false);
profileRemoveBtn->setEnabled(false);
}
}
QCheckBox *GeneralFilter::createExcludeCheckBox(const KConfigGroup &group)
{
QCheckBox *excludeCheckBox = new QCheckBox(this);
excludeCheckBox->setText(i18n("Exclude Folder Names"));
excludeCheckBox->setToolTip(i18n("Filters out specified directory names from the results."));
excludeCheckBox->setChecked(static_cast(group.readEntry("ExcludeFolderNamesUse", 0)));
return excludeCheckBox;
}
KHistoryComboBox *GeneralFilter::createExcludeComboBox(const KConfigGroup &group)
{
KHistoryComboBox *excludeComboBox = new KHistoryComboBox(false, this);
QSizePolicy excludeFolderNamesPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
excludeFolderNamesPolicy.setHeightForWidth(excludeComboBox->sizePolicy().hasHeightForWidth());
excludeComboBox->setSizePolicy(excludeFolderNamesPolicy);
excludeComboBox->setEditable(true);
excludeComboBox->setDuplicatesEnabled(false);
excludeComboBox->setMaxCount(25);
excludeComboBox->setMinimumContentsLength(10);
excludeComboBox->lineEdit()->setPlaceholderText(i18n("Enter space-separated folder names"));
excludeComboBox->lineEdit()->setWhatsThis(
i18n("You can insert names with escaped spaces or quoted.\nExample: .git \"target "
"build\" build\\ krusader"));
excludeComboBox->setHistoryItems(group.readEntry("ExcludeFolderNamesHistory", QStringList()));
excludeComboBox->setEditText(group.readEntry("ExcludeFolderNames", ""));
return excludeComboBox;
}
void GeneralFilter::slotAddBtnClicked()
{
profileManager->newProfile(searchFor->currentText().simplified());
refreshProfileListBox();
}
void GeneralFilter::slotOverwriteBtnClicked()
{
QListWidgetItem *item = profileListBox->currentItem();
if (item != 0)
profileManager->overwriteProfile(item->text());
}
void GeneralFilter::slotRemoveBtnClicked()
{
QListWidgetItem *item = profileListBox->currentItem();
if (item != 0) {
profileManager->deleteProfile(item->text());
refreshProfileListBox();
}
}
void GeneralFilter::slotProfileDoubleClicked(QListWidgetItem *item)
{
if (item != 0) {
QString profileName = item->text();
profileManager->loadProfile(profileName);
fltTabs->close(true);
}
}
void GeneralFilter::slotLoadBtnClicked()
{
QListWidgetItem *item = profileListBox->currentItem();
if (item != 0)
profileManager->loadProfile(item->text());
}
void GeneralFilter::slotDisable()
{
bool state = containsRegExp->isChecked();
bool global = ofType->currentText() != i18n("Folders");
bool remoteOnly = false;
if (properties & FilterTabs::HasSearchIn) {
QList urlList = searchIn->urlList();
remoteOnly = urlList.count() != 0;
foreach(const QUrl &url, urlList)
if (url.scheme() == "file")
remoteOnly = false;
}
containsWholeWord->setEnabled(!state && global);
containsRegExp->menu()->setEnabled(state && global);
encLabel->setEnabled(global);
contentEncoding->setEnabled(global);
containsTextCase->setEnabled(global);
containsRegExp->setEnabled(global);
if (properties & FilterTabs::HasRecurseOptions)
searchInArchives->setEnabled(global && !remoteOnly);
containsLabel->setEnabled(global);
containsText->setEnabled(global);
}
void GeneralFilter::slotRegExpTriggered(QAction * act)
{
if (act == 0)
return;
RegExpAction *regAct = dynamic_cast(act);
if (regAct == 0)
return;
containsText->lineEdit()->insert(regAct->regExp());
containsText->lineEdit()->setCursorPosition(containsText->lineEdit()->cursorPosition() + regAct->cursor());
containsText->lineEdit()->setFocus();
}
bool GeneralFilter::getSettings(FilterSettings &s)
{
// check that we have (at least) what to search, and where to search in
if (searchFor->currentText().simplified().isEmpty()) {
KMessageBox::error(this , i18n("No search criteria entered."));
searchFor->setFocus();
return false;
}
s.searchFor = searchFor->currentText().trimmed();
s.searchForCase = searchForCase->isChecked();
if (ofType->currentText() != i18n("All Files"))
s.mimeType = ofType->currentText();
if (containsText->isEnabled()) {
s.containsText = containsText->currentText();
s.containsTextCase = containsTextCase->isChecked();
s.containsWholeWord = containsWholeWord->isChecked();
s.containsRegExp = containsRegExp->isChecked();
}
if (contentEncoding->currentIndex() != 0)
s.contentEncoding =
KCharsets::charsets()->encodingForName(contentEncoding->currentText());
if (properties & FilterTabs::HasRecurseOptions) {
s.recursive = searchInDirs->isChecked();
s.searchInArchives = searchInArchives->isChecked();
s.followLinks = followLinks->isChecked();
}
if (properties & FilterTabs::HasSearchIn) {
s.searchIn = searchIn->urlList();
if (s.searchIn.isEmpty()) { // we need a place to search in
KMessageBox::error(this , i18n("Please specify a location to search in."));
searchIn->lineEdit()->setFocus();
return false;
}
}
if (properties & FilterTabs::HasDontSearchIn) {
s.dontSearchIn = dontSearchIn->urlList();
if (properties & FilterTabs::HasRecurseOptions) {
if (useExcludeFolderNames->isChecked()) {
s.excludeFolderNames = KShell::splitArgs(excludeFolderNames->currentText());
} else {
s.excludeFolderNames = QStringList();
}
}
}
return true;
}
void GeneralFilter::applySettings(const FilterSettings &s)
{
searchFor->setEditText(s.searchFor);
searchForCase->setChecked(s.searchForCase);
setComboBoxValue(ofType, s.mimeType);
containsText->setEditText(s.containsText);
containsTextCase->setChecked(s.containsTextCase);
containsWholeWord->setChecked(s.containsWholeWord);
containsRegExp->setChecked(s.containsRegExp);
setComboBoxValue(contentEncoding,
KCharsets::charsets()->descriptionForEncoding(s.contentEncoding));
if (properties & FilterTabs::HasRecurseOptions) {
searchInDirs->setChecked(s.recursive);
searchInArchives->setChecked(s.searchInArchives);
followLinks->setChecked(s.followLinks);
}
if (properties & FilterTabs::HasSearchIn) {
searchIn->lineEdit()->clear();
searchIn->listBox()->clear();
searchIn->listBox()->addItems(KrServices::toStringList(s.searchIn));
}
if (properties & FilterTabs::HasDontSearchIn) {
dontSearchIn->lineEdit()->clear();
dontSearchIn->listBox()->clear();
dontSearchIn->listBox()->addItems(KrServices::toStringList(s.dontSearchIn));
}
}
diff --git a/krusader/GUI/kcmdline.cpp b/krusader/GUI/kcmdline.cpp
index 09d6040c..81bad6ae 100644
--- a/krusader/GUI/kcmdline.cpp
+++ b/krusader/GUI/kcmdline.cpp
@@ -1,315 +1,315 @@
/*****************************************************************************
* Copyright (C) 2000 Shie Erlich *
* Copyright (C) 2000 Rafi Yanai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "kcmdline.h"
// QtCore
#include
#include
#include
// QtGui
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include "../krglobal.h"
#include "../icon.h"
#include "../krslots.h"
#include "../defaults.h"
#include "../krusaderview.h"
#include "../krservices.h"
#include "../ActionMan/addplaceholderpopup.h"
#include "kcmdmodebutton.h"
CmdLineCombo::CmdLineCombo(QWidget *parent) : KHistoryComboBox(parent), _handlingLineEditResize(false)
{
lineEdit()->installEventFilter(this);
_pathLabel = new QLabel(this);
_pathLabel->setWhatsThis(i18n("Name of folder where command will be processed."));
_pathLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
}
bool CmdLineCombo::eventFilter(QObject *watched, QEvent *e)
{
if(watched == lineEdit() && (e->type() == QEvent::Move || e->type() == QEvent::Resize)) {
if(!_handlingLineEditResize) { // avoid infinite recursion
_handlingLineEditResize = true;
updateLineEditGeometry();
_handlingLineEditResize = false;
}
}
return false;
}
void CmdLineCombo::setPath(QString path)
{
_path = path;
doLayout();
}
void CmdLineCombo::updateLineEditGeometry()
{
QRect r = lineEdit()->geometry();
r.setLeft(_pathLabel->geometry().right());
lineEdit()->setGeometry(r);
}
void CmdLineCombo::doLayout()
{
QString pathNameLabel = _path;
QFontMetrics fm(_pathLabel->fontMetrics());
int textWidth = fm.width(_path);
int maxWidth = (width() + _pathLabel->width()) * 2 / 5;
int letters = _path.length() / 2;
while (letters && textWidth > maxWidth) {
pathNameLabel = _path.left(letters) + "..." + _path.right(letters);
letters--;
textWidth = fm.width(pathNameLabel);
}
_pathLabel->setText(pathNameLabel + "> ");
_pathLabel->adjustSize();
QStyleOptionComboBox opt;
initStyleOption(&opt);
QRect labelRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
QStyle::SC_ComboBoxEditField, this);
labelRect.adjust(2, 0, 0, 0);
labelRect.setWidth(_pathLabel->width());
_pathLabel->setGeometry(labelRect);
updateLineEditGeometry();
}
void CmdLineCombo::resizeEvent(QResizeEvent *e)
{
KHistoryComboBox::resizeEvent(e);
doLayout();
}
void CmdLineCombo::keyPressEvent(QKeyEvent *e)
{
switch (e->key()) {
case Qt::Key_Enter:
case Qt::Key_Return:
if (e->modifiers() & Qt::ControlModifier) {
SLOTS->insertFileName((e->modifiers()&Qt::ShiftModifier)!=0);
break;
}
KHistoryComboBox::keyPressEvent(e);
break;
case Qt::Key_Down:
if (e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
MAIN_VIEW->focusTerminalEmulator();
return;
} else
KHistoryComboBox::keyPressEvent(e);
break;
case Qt::Key_Up:
if (e->modifiers() == Qt::ControlModifier || e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
emit returnToPanel();
return;
} else
KHistoryComboBox::keyPressEvent(e);
break;
case Qt::Key_Escape:
if (e->modifiers() == 0) {
emit returnToPanel();
return;
} else
KHistoryComboBox::keyPressEvent(e);
break;
default:
KHistoryComboBox::keyPressEvent(e);
}
}
KCMDLine::KCMDLine(QWidget *parent) : QWidget(parent)
{
QGridLayout * layout = new QGridLayout(this);
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
int height = QFontMetrics(QFontDatabase::systemFont(QFontDatabase::GeneralFont)).height();
height = height + 5 * (height > 14) + 6;
// and editable command line
completion.setMode(KUrlCompletion::FileCompletion);
cmdLine = new CmdLineCombo(this);
cmdLine->setMaxCount(100); // remember 100 commands
cmdLine->setMinimumContentsLength(10);
cmdLine->setDuplicatesEnabled(false);
cmdLine->setMaximumHeight(height);
cmdLine->setCompletionObject(&completion);
cmdLine->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
// load the history
KConfigGroup grpSvr(krConfig, "Private");
QStringList list = grpSvr.readEntry("cmdline history", QStringList());
cmdLine->setHistoryItems(list);
- connect(cmdLine, SIGNAL(returnPressed(QString)), this, SLOT(slotRun()));
- connect(cmdLine, SIGNAL(returnPressed(QString)), cmdLine->lineEdit(), SLOT(clear()));
- connect(cmdLine, SIGNAL(returnToPanel()), this, SLOT(slotReturnFocus()));
+ connect(cmdLine, QOverload::of(&CmdLineCombo::returnPressed), this, &KCMDLine::slotRun);
+ connect(cmdLine, QOverload::of(&CmdLineCombo::returnPressed), cmdLine->lineEdit(), &QLineEdit::clear);
+ connect(cmdLine, &CmdLineCombo::returnToPanel, this, &KCMDLine::slotReturnFocus);
cmdLine->setWhatsThis(i18n("Well, it is actually quite simple: you type your command here and Krusader obeys.
Tip: move within command line history with <Up> and <Down> arrows.
"));
layout->addWidget(cmdLine, 0, 1);
buttonAddPlaceholder = new QToolButton(this);
buttonAddPlaceholder->setAutoRaise(true);
buttonAddPlaceholder->setIcon(Icon("list-add"));
- connect(buttonAddPlaceholder, SIGNAL(clicked()), this, SLOT(addPlaceholder()));
+ connect(buttonAddPlaceholder, &QToolButton::clicked, this, &KCMDLine::addPlaceholder);
buttonAddPlaceholder->setWhatsThis(i18n("Add Placeholders for the selected files in the panel."));
layout->addWidget(buttonAddPlaceholder, 0, 2);
// a run in terminal button
terminal = new KCMDModeButton(this);
terminal->setAutoRaise(true);
layout->addWidget(terminal, 0, 3);
layout->activate();
}
KCMDLine::~KCMDLine()
{
KConfigGroup grpSvr(krConfig, "Private");
QStringList list = cmdLine->historyItems();
//qWarning() << list[0];
grpSvr.writeEntry("cmdline history", list);
krConfig->sync();
}
void KCMDLine::addPlaceholder()
{
AddPlaceholderPopup popup(this);
QString exp = popup.getPlaceholder(
buttonAddPlaceholder->mapToGlobal(QPoint(0, 0))
);
this->addText(exp);
}
void KCMDLine::setCurrent(const QString &path)
{
cmdLine->setPath(path);
completion.setDir(QUrl::fromLocalFile(path));
// make sure our command is executed in the right directory
// This line is important for Krusader overall functions -> do not remove !
QDir::setCurrent(path);
}
void KCMDLine::slotRun()
{
const QString command1(cmdLine->currentText());
if (command1.isEmpty())
return;
cmdLine->addToHistory(command1);
// bugfix by aardvark: current editline is destroyed by addToHistory() in some cases
cmdLine->setEditText(command1);
if (command1.simplified().left(3) == "cd ") { // cd command effect the active panel
QString dir = command1.right(command1.length() - command1.indexOf(" ")).trimmed();
if (dir == "~")
dir = QDir::homePath();
else if (dir.left(1) != "/" && !dir.contains(":/"))
dir = cmdLine->path() + (cmdLine->path() == "/" ? "" : "/") + dir;
SLOTS->refresh(QUrl::fromUserInput(dir,QDir::currentPath(),QUrl::AssumeLocalFile));
} else {
exec();
cmdLine->clearEditText();
}
}
void KCMDLine::slotReturnFocus()
{
MAIN_VIEW->cmdLineUnFocus();
}
static const KrActionBase::ExecType execModesMenu[] = {
KrActionBase::Normal,
KrActionBase::CollectOutputSeparateStderr,
KrActionBase::CollectOutput,
KrActionBase::Terminal,
KrActionBase::RunInTE,
};
QString KCMDLine::command() const
{
return cmdLine->currentText();
}
KrActionBase::ExecType KCMDLine::execType() const
{
KConfigGroup grp(krConfig, "Private");
int i = grp.readEntry("Command Execution Mode", (int)0);
return execModesMenu[i];
}
QString KCMDLine::startpath() const
{
return cmdLine->path();
// return path->text().left(path->text().length() - 1);
}
QString KCMDLine::user() const
{
return QString();
}
QString KCMDLine::text() const
{
return cmdLine->currentText();
}
bool KCMDLine::acceptURLs() const
{
return false;
}
bool KCMDLine::confirmExecution() const
{
return false;
}
bool KCMDLine::doSubstitution() const
{
return true;
}
void KCMDLine::setText(QString text)
{
cmdLine->lineEdit()->setText(text);
}
diff --git a/krusader/GUI/terminaldock.cpp b/krusader/GUI/terminaldock.cpp
index 29a59fd9..5d92ffbd 100644
--- a/krusader/GUI/terminaldock.cpp
+++ b/krusader/GUI/terminaldock.cpp
@@ -1,289 +1,289 @@
/*****************************************************************************
* Copyright (C) 2008 Václav Juza *
* Copyright (C) 2008-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "terminaldock.h"
// QtCore
#include
#include
#include
#include
#include
#include
// QtGui
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kcmdline.h"
#include "../kractions.h"
#include "../krmainwindow.h"
#include "../krservices.h"
#include "../krslots.h"
#include "../krusaderview.h"
#include "../FileSystem/filesystem.h"
#include "../Panel/PanelView/krview.h"
#include "../Panel/listpanel.h"
#include "../Panel/listpanelactions.h"
#include "../Panel/panelfunc.h"
/**
* A widget containing the konsolepart for the Embedded terminal emulator
*/
TerminalDock::TerminalDock(QWidget* parent, KrMainWindow *mainWindow) : QWidget(parent),
_mainWindow(mainWindow), konsole_part(0), t(0), initialised(false), firstInput(true)
{
terminal_hbox = new QHBoxLayout(this);
}
TerminalDock::~TerminalDock()
{
}
bool TerminalDock::initialise()
{
if (! initialised) { // konsole part is not yet loaded or it has already failed
KService::Ptr service = KService::serviceByDesktopName("konsolepart");
if (service) {
QWidget *focusW = qApp->focusWidget();
// Create the part
QString error;
konsole_part = service->createInstance(this, this, QVariantList(), &error);
if (konsole_part) { //loaded successfully
terminal_hbox->addWidget(konsole_part->widget());
setFocusProxy(konsole_part->widget());
connect(konsole_part, &KParts::ReadOnlyPart::destroyed, this,
&TerminalDock::killTerminalEmulator);
// must filter app events, because some of them are processed
// by child widgets of konsole_part->widget()
// and would not be received on konsole_part->widget()
qApp->installEventFilter(this);
t = qobject_cast(konsole_part);
if (t) {
lastPath = QDir::currentPath();
t->showShellInDir(lastPath);
}
initialised = true;
firstInput = true;
} else
KMessageBox::error(0, i18n("Cannot create embedded terminal.
"
"The reported error was: %1", error));
// the Terminal Emulator may be hidden (if we are creating it only
// to send command there and see the results later)
if (focusW) {
focusW->setFocus();
} else {
ACTIVE_PANEL->gui->slotFocusOnMe();
}
} else
KMessageBox::sorry(0, i18nc("missing program - arg1 is a URL",
"Cannot create embedded terminal.
"
"You can fix this by installing Konsole:
%1",
QString("%1").arg(
"http://www.kde.org/applications/system/konsole")),
0, KMessageBox::AllowLink);
}
return isInitialised();
}
void TerminalDock::killTerminalEmulator()
{
qDebug() << "killed";
initialised = false;
konsole_part = NULL;
t = NULL;
qApp->removeEventFilter(this);
MAIN_VIEW->setTerminalEmulator(false);
}
void TerminalDock::sendInput(const QString& input, bool clearCommand)
{
if (!t)
return;
if (clearCommand) {
// send SIGINT before input command to avoid unwanted behaviour when current line is not empty
// and command is appended to current input (e.g. "rm -rf x " concatenated with 'cd /usr');
// code "borrowed" from Dolphin, Copyright (C) 2007-2010 by Peter Penz
const int processId = t->terminalProcessId();
// workaround (firstInput): kill is sent to terminal if shell is not initialized yet
if (processId > 0 && !firstInput) {
kill(processId, SIGINT);
}
}
firstInput = false;
t->sendInput(input);
}
/*! Sends a `cd` command to the embedded terminal emulator so as to synchronize the directory of the actual panel and
the directory of the embedded terminal emulator.
To avoid that Krusader's embedded terminal adds a lot of `cd` messages to the shell history: the user has to use
bash and have set `HISTCONTROL=ignorespace` or `HISTCONTROL=ignoreboth` (which is the default in a lot of Linux
distributions so in that case the user hasn't got to do anything), or the user has to use an equivalent method.
*/
void TerminalDock::sendCd(const QString& path)
{
if (path.compare(lastPath) != 0) {
// A space exists in front of the `cd` so as to avoid that Krusader's embedded terminal adds a lot of `cd`
// messages to the shell history, in Dolphin it's done the same way: https://bugs.kde.org/show_bug.cgi?id=204039
sendInput(QString(" cd ") + KrServices::quote(path) + QString("\n"));
lastPath = path;
}
}
bool TerminalDock::applyShortcuts(QKeyEvent * ke)
{
int pressedKey = (ke->key() | ke->modifiers());
// TODO KF5 removed
if (KrActions::actToggleTerminal->shortcut().matches(pressedKey)) {
KrActions::actToggleTerminal->activate(QAction::Trigger);
return true;
}
if (!krSwitchFullScreenTE->shortcut().isEmpty() && krSwitchFullScreenTE->shortcut().matches(pressedKey)) {
krSwitchFullScreenTE->activate(QAction::Trigger);
return true;
}
if (_mainWindow->listPanelActions()->actPaste->shortcut().matches(pressedKey)) {
QString text = QApplication::clipboard()->text();
if (! text.isEmpty()) {
text.replace('\n', '\r');
sendInput(text, false);
}
return true;
}
//insert current to the terminal
if ((ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return) &&
(ke->modifiers() & Qt::ControlModifier)) {
SLOTS->insertFileName((ke->modifiers()&Qt::ShiftModifier)!=0);
return true;
}
//navigation
if ((ke->key() == Qt::Key_Down) && (ke->modifiers() == Qt::ControlModifier)) {
if (MAIN_VIEW->cmdLine()->isVisible()) {
MAIN_VIEW->cmdLine()->setFocus();
}
return true;
} else if ((ke->key() == Qt::Key_Up)
&& ((ke->modifiers() == Qt::ControlModifier)
|| (ke->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)))) {
ACTIVE_PANEL->gui->slotFocusOnMe();
return true;
}
return false;
}
bool TerminalDock::eventFilter(QObject * watched, QEvent * e)
{
if (konsole_part == NULL || konsole_part->widget() == NULL)
return false;
// we must watch for child widgets as well,
// otherwise some shortcuts are "eaten" by them before
// being processed in konsole_part->widget() context
// examples are Ctrl+F, Ctrl+Enter
QObject *w;
for (w = watched; w != NULL; w = w->parent())
if (w == konsole_part->widget())
break;
if (w == NULL) // is not a child of konsole_part
return false;
switch (e->type()) {
case QEvent::ShortcutOverride: {
QKeyEvent *ke = (QKeyEvent *)e;
// If not present, some keys would be considered a shortcut, for example "a"
if ((ke->key() == Qt::Key_Insert) && (ke->modifiers() == Qt::ShiftModifier)) {
ke->accept();
return true;
}
if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier) &&
(ke->key() >= 32) && (ke->key() <= 127)) {
ke->accept();
return true;
}
break;
}
case QEvent::KeyPress: {
QKeyEvent *ke = (QKeyEvent *)e;
if (applyShortcuts(ke)) {
ke->accept();
return true;
}
break;
}
default:
return false;
}
return false;
}
bool TerminalDock::isTerminalVisible() const
{
return isVisible() && konsole_part != NULL && konsole_part->widget() != NULL
&& konsole_part->widget()->isVisible();
}
bool TerminalDock::isInitialised() const
{
return konsole_part != NULL && konsole_part->widget() != NULL;
}
void TerminalDock::hideEvent(QHideEvent * /*e*/)
{
// BUGFIX: when the terminal emulator is toggled on, first it is shown in minimum size
// then QSplitter resizes it to the desired size.
// this minimum resize scrolls up the content of the konsole widget
// SOLUTION:
// we hide the console widget while the resize ceremony happens, then reenable it
if (konsole_part && konsole_part->widget())
konsole_part->widget()->hide(); // hide the widget to prevent from resize
}
void TerminalDock::showEvent(QShowEvent * /*e*/)
{
if (konsole_part && konsole_part->widget()) {
// BUGFIX: TE scrolling bug (see upper)
// show the Konsole part delayed
- QTimer::singleShot(0, konsole_part->widget(), SLOT(show()));
+ QTimer::singleShot(0, konsole_part->widget(), &QWidget::show);
}
}
diff --git a/krusader/KViewer/krviewer.cpp b/krusader/KViewer/krviewer.cpp
index db166ba7..b9efbbb5 100644
--- a/krusader/KViewer/krviewer.cpp
+++ b/krusader/KViewer/krviewer.cpp
@@ -1,711 +1,711 @@
/*****************************************************************************
* Copyright (C) 2002 Shie Erlich *
* Copyright (C) 2002 Rafi Yanai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "krviewer.h"
// QtCore
#include
#include
#include
#include
#include
// QtGui
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "../defaults.h"
#include "../icon.h"
#include "panelviewer.h"
#define VIEW_ICON "document-preview"
#define EDIT_ICON "document-edit"
#define MODIFIED_ICON "document-save-as"
#define CHECK_MODFIED_INTERVAL 500
/*
NOTE: Currently the code expects PanelViewer::openUrl() to be called only once
in the panel viewer's life time - otherwise unexpected things might happen.
*/
QList KrViewer::viewers;
KrViewer::KrViewer(QWidget *parent) :
KParts::MainWindow(parent, (Qt::WindowFlags)KDE_DEFAULT_WINDOWFLAGS), manager(this, this), tabBar(this),
reservedKeys(), reservedKeyActions(), sizeX(-1), sizeY(-1)
{
//setWFlags(Qt::WType_TopLevel | WDestructiveClose);
setXMLFile("krviewer.rc"); // kpart-related xml file
setHelpMenuEnabled(false);
connect(&manager, &KParts::PartManager::activePartChanged, this, &KrViewer::createGUI);
connect(&tabBar, &QTabWidget::currentChanged, this, &KrViewer::tabChanged);
connect(&tabBar, &QTabWidget::tabCloseRequested, this, [=](int index) { tabCloseRequest(index, false); });
tabBar.setDocumentMode(true);
tabBar.setMovable(true);
setCentralWidget(&tabBar);
printAction = KStandardAction::print(this, SLOT(print()), 0);
copyAction = KStandardAction::copy(this, SLOT(copy()), 0);
viewerMenu = new QMenu(this);
QAction *tempAction;
KActionCollection *ac = actionCollection();
#define addCustomMenuAction(name, text, slot, shortcut)\
tempAction = ac->addAction(name, this, slot);\
tempAction->setText(text);\
ac->setDefaultShortcut(tempAction, shortcut);\
viewerMenu->addAction(tempAction);
addCustomMenuAction("genericViewer", i18n("&Generic Viewer"), SLOT(viewGeneric()), Qt::CTRL + Qt::SHIFT + Qt::Key_G);
addCustomMenuAction("textViewer", i18n("&Text Viewer"), SLOT(viewText()), Qt::CTRL + Qt::SHIFT + Qt::Key_T);
addCustomMenuAction("hexViewer", i18n("&Hex Viewer"), SLOT(viewHex()), Qt::CTRL + Qt::SHIFT + Qt::Key_H);
addCustomMenuAction("lister", i18n("&Lister"), SLOT(viewLister()), Qt::CTRL + Qt::SHIFT + Qt::Key_L);
viewerMenu->addSeparator();
addCustomMenuAction("textEditor", i18n("Text &Editor"), SLOT(editText()), Qt::CTRL + Qt::SHIFT + Qt::Key_E);
viewerMenu->addSeparator();
QList actList = menuBar()->actions();
bool hasPrint = false, hasCopy = false;
foreach(QAction *a, actList) {
if (a->shortcut().matches(printAction->shortcut()) != QKeySequence::NoMatch)
hasPrint = true;
if (a->shortcut().matches(copyAction->shortcut()) != QKeySequence::NoMatch)
hasCopy = true;
}
QAction *printAct = viewerMenu->addAction(printAction->icon(), printAction->text(), this, SLOT(print()));
if (hasPrint)
printAct->setShortcut(printAction->shortcut());
QAction *copyAct = viewerMenu->addAction(copyAction->icon(), copyAction->text(), this, SLOT(copy()));
if (hasCopy)
copyAct->setShortcut(copyAction->shortcut());
viewerMenu->addSeparator();
configKeysAction = ac->addAction(KStandardAction::KeyBindings, this, SLOT(configureShortcuts()));
viewerMenu->addAction(configKeysAction);
viewerMenu->addSeparator();
detachAction = ac->addAction("detachTab", this, SLOT(detachTab()));
detachAction->setText(i18n("&Detach Tab"));
//no point in detaching only one tab..
detachAction->setEnabled(false);
ac->setDefaultShortcut(detachAction, Qt::META + Qt::Key_D);
viewerMenu->addAction(detachAction);
quitAction = ac->addAction(KStandardAction::Quit, this, SLOT(close()));
viewerMenu->addAction(quitAction);
QList shortcuts;
tabCloseAction = ac->addAction("closeTab", this, SLOT(tabCloseRequest()));
tabCloseAction->setText(i18n("&Close Current Tab"));
shortcuts = KStandardShortcut::close();
shortcuts.append(Qt::Key_Escape);
ac->setDefaultShortcuts(tabCloseAction, shortcuts);
tabNextAction = ac->addAction("nextTab", this, SLOT(nextTab()));
tabNextAction->setText(i18n("&Next Tab"));
shortcuts = KStandardShortcut::tabNext();
shortcuts.append(Qt::CTRL + Qt::Key_Tab); // reenforce QTabWidget shortcut
ac->setDefaultShortcuts(tabNextAction, shortcuts);
tabPrevAction = ac->addAction("prevTab", this, SLOT(prevTab()));
tabPrevAction->setText(i18n("&Previous Tab"));
shortcuts = KStandardShortcut::tabPrev();
shortcuts.append(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab); // reenforce QTabWidget shortcut
ac->setDefaultShortcuts(tabPrevAction, shortcuts);
tabBar.setTabsClosable(true);
checkModified();
KConfigGroup group(krConfig, "KrViewerWindow");
int sx = group.readEntry("Window Width", -1);
int sy = group.readEntry("Window Height", -1);
if (sx != -1 && sy != -1)
resize(sx, sy);
else
resize(900, 700);
if (group.readEntry("Window Maximized", false)) {
setWindowState(windowState() | Qt::WindowMaximized);
}
// filtering out the key events
menuBar() ->installEventFilter(this);
}
KrViewer::~KrViewer()
{
disconnect(&manager, SIGNAL(activePartChanged(KParts::Part*)),
this, SLOT(createGUI(KParts::Part*)));
viewers.removeAll(this);
// close tabs before deleting tab bar - this avoids Qt bug 26115
// https://bugreports.qt-project.org/browse/QTBUG-26115
while(tabBar.count())
tabCloseRequest(tabBar.currentIndex(), true);
delete printAction;
delete copyAction;
}
void KrViewer::configureDeps()
{
PanelEditor::configureDeps();
}
void KrViewer::createGUI(KParts::Part* part)
{
KParts::MainWindow::createGUI(part);
updateActions();
toolBar() ->show();
statusBar() ->show();
// the KParts part may override the viewer shortcuts. We prevent it
// by installing an event filter on the menuBar() and the part
reservedKeys.clear();
reservedKeyActions.clear();
QList list = viewerMenu->actions();
// also add the actions that are not in the menu...
list << tabCloseAction << tabNextAction << tabPrevAction;
// getting the key sequences of the viewer menu
for (int w = 0; w != list.count(); w++) {
QAction *act = list[ w ];
QList sequences = act->shortcuts();
foreach(QKeySequence keySeq, sequences) {
for(int i = 0; i < keySeq.count(); ++i) {
reservedKeys.push_back(keySeq[i]);
reservedKeyActions.push_back(act); //the same action many times in case of multiple shortcuts
}
}
}
// and "fix" the menubar
QList actList = menuBar()->actions();
viewerMenu->setTitle(i18n("&KrViewer"));
QAction * act = menuBar() ->addMenu(viewerMenu);
act->setData(QVariant(70));
menuBar() ->show();
}
void KrViewer::configureShortcuts()
{
KShortcutsDialog::configure(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, this);
}
bool KrViewer::eventFilter(QObject * /* watched */, QEvent * e)
{
// TODO: after porting to Qt5/KF5 we never catch *ANY* KeyPress or ShortcutOverride events here anymore.
// Should look into if there is any way to fix it. Currently if a KPart has same shortcut as KrViewer then
// it causes a conflict, messagebox shown to user and no action triggered.
if (e->type() == QEvent::ShortcutOverride) {
QKeyEvent* ke = (QKeyEvent*) e;
if (reservedKeys.contains(ke->key())) {
ke->accept();
QAction *act = reservedKeyActions[ reservedKeys.indexOf(ke->key())];
if (act != 0) {
// don't activate the close functions immediately!
// it can cause crash
if (act == tabCloseAction || act == quitAction) {
- QTimer::singleShot(0, act, SLOT(trigger()));
+ QTimer::singleShot(0, act, &QAction::trigger);
} else {
act->activate(QAction::Trigger);
}
}
return true;
}
} else if (e->type() == QEvent::KeyPress) {
QKeyEvent* ke = (QKeyEvent*) e;
if (reservedKeys.contains(ke->key())) {
ke->accept();
return true;
}
}
return false;
}
KrViewer* KrViewer::getViewer(bool new_window)
{
if (!new_window) {
if (viewers.isEmpty()) {
viewers.prepend(new KrViewer()); // add to first (active)
} else {
if (viewers.first()->isMinimized()) { // minimized? -> show it again
viewers.first()->setWindowState((viewers.first()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
viewers.first()->show();
}
viewers.first()->raise();
viewers.first()->activateWindow();
}
return viewers.first();
} else {
KrViewer *newViewer = new KrViewer();
viewers.prepend(newViewer);
return newViewer;
}
}
void KrViewer::view(QUrl url, QWidget * parent)
{
KConfigGroup group(krConfig, "General");
bool defaultWindow = group.readEntry("View In Separate Window", _ViewInSeparateWindow);
view(url, Default, defaultWindow, parent);
}
void KrViewer::view(QUrl url, Mode mode, bool new_window, QWidget * parent)
{
KrViewer* viewer = getViewer(new_window);
viewer->viewInternal(url, mode, parent);
viewer->show();
}
void KrViewer::edit(QUrl url, QWidget * parent)
{
edit(url, Text, -1, parent);
}
void KrViewer::edit(QUrl url, Mode mode, int new_window, QWidget * parent)
{
KConfigGroup group(krConfig, "General");
QString editor = group.readEntry("Editor", _Editor);
if (new_window == -1)
new_window = group.readEntry("View In Separate Window", _ViewInSeparateWindow);
if (editor != "internal editor" && !editor.isEmpty()) {
KProcess proc;
QStringList cmdArgs = KShell::splitArgs(editor, KShell::TildeExpand);
if (cmdArgs.isEmpty()) {
KMessageBox::error(krMainWindow,
i18nc("Arg is a string containing the bad quoting.",
"Bad quoting in editor command:\n%1", editor));
return;
}
// if the file is local, pass a normal path and not a url. this solves
// the problem for editors that aren't url-aware
proc << cmdArgs << url.toDisplayString(QUrl::PreferLocalFile);
if (!proc.startDetached())
KMessageBox::sorry(krMainWindow, i18n("Can not open \"%1\"", editor));
return;
}
KrViewer* viewer = getViewer(new_window);
viewer->editInternal(url, mode, parent);
viewer->show();
}
void KrViewer::addTab(PanelViewerBase *pvb)
{
int tabIndex = tabBar.addTab(pvb, makeTabIcon(pvb), makeTabText(pvb));
tabBar.setCurrentIndex(tabIndex);
tabBar.setTabToolTip(tabIndex, makeTabToolTip(pvb));
updateActions();
// now we can offer the option to detach tabs (we have more than one)
if (tabBar.count() > 1) {
detachAction->setEnabled(true);
}
tabBar.show();
connect(pvb, &PanelViewerBase::openUrlFinished, this, &KrViewer::openUrlFinished);
connect(pvb, &PanelViewerBase::urlChanged, this, &KrViewer::tabURLChanged);
}
void KrViewer::tabURLChanged(PanelViewerBase *pvb, const QUrl &url)
{
Q_UNUSED(url)
refreshTab(pvb);
}
void KrViewer::openUrlFinished(PanelViewerBase *pvb, bool success)
{
if (success) {
KParts::ReadOnlyPart *part = pvb->part();
if (part) {
if (!isPartAdded(part))
addPart(part);
if (tabBar.currentWidget() == pvb) {
manager.setActivePart(part);
if (part->widget())
part->widget()->setFocus();
}
}
} else {
tabCloseRequest(tabBar.currentIndex(), false);
}
}
void KrViewer::tabChanged(int index)
{
QWidget *w = tabBar.widget(index);
if(!w) return;
KParts::ReadOnlyPart *part = static_cast(w)->part();
if (part && isPartAdded(part)) {
manager.setActivePart(part);
if (part->widget())
part->widget()->setFocus();
} else
manager.setActivePart(0);
// set this viewer to be the main viewer
if (viewers.removeAll(this)) viewers.prepend(this); // move to first
}
void KrViewer::tabCloseRequest(int index, bool force)
{
// important to save as returnFocusTo will be cleared at removePart
QWidget *returnFocusToThisWidget = returnFocusTo;
PanelViewerBase *pvb = static_cast(tabBar.widget(index));
if (!pvb)
return;
if (!force && !pvb->queryClose())
return;
if (pvb->part() && isPartAdded(pvb->part()))
removePart(pvb->part());
disconnect(pvb, 0, this, 0);
pvb->closeUrl();
tabBar.removeTab(index);
delete pvb;
pvb = 0;
if (tabBar.count() <= 0) {
if (returnFocusToThisWidget) {
returnFocusToThisWidget->raise();
returnFocusToThisWidget->activateWindow();
} else {
krMainWindow->raise();
krMainWindow->activateWindow();
}
- QTimer::singleShot(0, this, SLOT(close()));
+ QTimer::singleShot(0, this, &KrViewer::close);
} else if (tabBar.count() == 1) {
// no point in detaching only one tab..
detachAction->setEnabled(false);
}
}
void KrViewer::tabCloseRequest()
{
tabCloseRequest(tabBar.currentIndex());
}
bool KrViewer::queryClose()
{
KConfigGroup group(krConfig, "KrViewerWindow");
group.writeEntry("Window Width", sizeX);
group.writeEntry("Window Height", sizeY);
group.writeEntry("Window Maximized", isMaximized());
for (int i = 0; i != tabBar.count(); i++) {
PanelViewerBase* pvb = static_cast(tabBar.widget(i));
if (!pvb)
continue;
tabBar.setCurrentIndex(i);
if (!pvb->queryClose())
return false;
}
return true;
}
void KrViewer::viewGeneric()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (pvb)
viewInternal(pvb->url(), Generic);
}
void KrViewer::viewText()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (pvb)
viewInternal(pvb->url(), Text);
}
void KrViewer::viewLister()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (pvb)
viewInternal(pvb->url(), Lister);
}
void KrViewer::viewHex()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (pvb)
viewInternal(pvb->url(), Hex);
}
void KrViewer::editText()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (pvb)
editInternal(pvb->url(), Text);
}
void KrViewer::checkModified()
{
- QTimer::singleShot(CHECK_MODFIED_INTERVAL, this, SLOT(checkModified()));
+ QTimer::singleShot(CHECK_MODFIED_INTERVAL, this, &KrViewer::checkModified);
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (pvb)
refreshTab(pvb);
}
void KrViewer::refreshTab(PanelViewerBase* pvb)
{
int ndx = tabBar.indexOf(pvb);
tabBar.setTabText(ndx, makeTabText(pvb));
tabBar.setTabIcon(ndx, makeTabIcon(pvb));
tabBar.setTabToolTip(ndx, makeTabToolTip(pvb));
}
void KrViewer::nextTab()
{
int index = (tabBar.currentIndex() + 1) % tabBar.count();
tabBar.setCurrentIndex(index);
}
void KrViewer::prevTab()
{
int index = (tabBar.currentIndex() - 1) % tabBar.count();
while (index < 0) index += tabBar.count();
tabBar.setCurrentIndex(index);
}
void KrViewer::detachTab()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (!pvb) return;
KrViewer* viewer = getViewer(true);
bool wasPartAdded = false;
KParts::ReadOnlyPart *part = pvb->part();
if (part && isPartAdded(part)) {
wasPartAdded = true;
removePart(part);
}
disconnect(pvb, 0, this, 0);
tabBar.removeTab(tabBar.indexOf(pvb));
if (tabBar.count() == 1) {
//no point in detaching only one tab..
detachAction->setEnabled(false);
}
pvb->setParent(&viewer->tabBar);
pvb->move(QPoint(0, 0));
viewer->addTab(pvb);
if (wasPartAdded) {
viewer->addPart(part);
if (part->widget())
part->widget()->setFocus();
}
viewer->show();
}
void KrViewer::changeEvent(QEvent *e)
{
if (e->type() == QEvent::ActivationChange && isActiveWindow())
if (viewers.removeAll(this)) viewers.prepend(this); // move to first
}
void KrViewer::print()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (!pvb || !pvb->part() || !isPartAdded(pvb->part()))
return;
KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject(pvb->part());
if (ext && ext->isActionEnabled("print"))
Invoker(ext, SLOT(print())).invoke();
}
void KrViewer::copy()
{
PanelViewerBase* pvb = static_cast(tabBar.currentWidget());
if (!pvb || !pvb->part() || !isPartAdded(pvb->part()))
return;
KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject(pvb->part());
if (ext && ext->isActionEnabled("copy"))
Invoker(ext, SLOT(copy())).invoke();
}
void KrViewer::updateActions()
{
QList actList = toolBar()->actions();
bool hasPrint = false, hasCopy = false;
foreach(QAction *a, actList) {
if (a->text() == printAction->text())
hasPrint = true;
if (a->text() == copyAction->text())
hasCopy = true;
}
if (!hasPrint)
toolBar()->addAction(printAction->icon(), printAction->text(), this, SLOT(print()));
if (!hasCopy)
toolBar()->addAction(copyAction->icon(), copyAction->text(), this, SLOT(copy()));
}
bool KrViewer::isPartAdded(KParts::Part* part)
{
return manager.parts().contains(part);
}
void KrViewer::resizeEvent(QResizeEvent *e)
{
if (!isMaximized()) {
sizeX = e->size().width();
sizeY = e->size().height();
}
KParts::MainWindow::resizeEvent(e);
}
QString KrViewer::makeTabText(PanelViewerBase *pvb)
{
QString fileName = pvb->url().fileName();
if (pvb->isModified())
fileName.prepend("*");
return pvb->isEditor() ?
i18nc("filename (filestate)", "%1 (Editing)", fileName) :
i18nc("filename (filestate)", "%1 (Viewing)", fileName);
}
QString KrViewer::makeTabToolTip(PanelViewerBase *pvb)
{
QString url = pvb->url().toDisplayString(QUrl::PreferLocalFile);
return pvb->isEditor() ?
i18nc("filestate: filename", "Editing: %1", url) :
i18nc("filestate: filename", "Viewing: %1", url);
}
QIcon KrViewer::makeTabIcon(PanelViewerBase *pvb)
{
QString iconName;
if (pvb->isModified())
iconName = MODIFIED_ICON;
else if (pvb->isEditor())
iconName = EDIT_ICON;
else
iconName = VIEW_ICON;
return Icon(iconName);
}
void KrViewer::addPart(KParts::ReadOnlyPart *part)
{
Q_ASSERT(part);
Q_ASSERT(!isPartAdded(part));
if (isPartAdded(part)) {
qDebug()<<"part already added:"<installEventFilter(this);
manager.addPart(part, false); // don't automatically set active part
}
void KrViewer::removePart(KParts::ReadOnlyPart *part)
{
Q_ASSERT(part);
Q_ASSERT(isPartAdded(part));
if (isPartAdded(part)) {
disconnect(part, 0, this, 0);
part->removeEventFilter(this);
manager.removePart(part);
} else
qDebug()<<"part hasn't been added:"<openUrl(url);
}
void KrViewer::editInternal(QUrl url, Mode mode, QWidget * parent)
{
returnFocusTo = parent;
PanelViewerBase* editWidget = new PanelEditor(&tabBar, mode);
addTab(editWidget);
editWidget->openUrl(url);
}
diff --git a/krusader/KViewer/lister.cpp b/krusader/KViewer/lister.cpp
index de750c80..a5b55dc1 100644
--- a/krusader/KViewer/lister.cpp
+++ b/krusader/KViewer/lister.cpp
@@ -1,2277 +1,2276 @@
/*****************************************************************************
* Copyright (C) 2009 Csaba Karai *
* Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "lister.h"
// QtCore
#include
#include
#include
#include
#include
// QtGui
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// QtPrintSupport
#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
#include
#include "../krglobal.h"
#include "../icon.h"
#include "../kractions.h"
#include "../GUI/krremoteencodingmenu.h"
#define SEARCH_CACHE_CHARS 100000
#define SEARCH_MAX_ROW_LEN 4000
#define CONTROL_CHAR 752
#define CACHE_SIZE 1048576 // cache size set to 1MiB
ListerTextArea::ListerTextArea(Lister *lister, QWidget *parent) : KTextEdit(parent), _lister(lister)
{
connect(this, &QTextEdit::cursorPositionChanged, this, &ListerTextArea::slotCursorPositionChanged);
_tabWidth = 4;
setWordWrapMode(QTextOption::NoWrap);
setLineWrapMode(QTextEdit::NoWrap);
// zoom shortcuts
connect(new QShortcut(QKeySequence("Ctrl++"), this), &QShortcut::activated, this, [=]() { zoomIn(); });
connect(new QShortcut(QKeySequence("Ctrl+-"), this), &QShortcut::activated, this, [=]() { zoomOut(); });
// start cursor blinking
connect(&_blinkTimer, &QTimer::timeout, this, [=] {
if (!_cursorBlinkMutex.tryLock()) {
return;
}
setCursorWidth(cursorWidth() == 0 ? 2 : 0);
_cursorBlinkMutex.unlock();
});
_blinkTimer.start(500);
}
void ListerTextArea::reset()
{
_screenStartPos = 0;
_cursorPos = 0;
_cursorAnchorPos = -1;
_cursorAtFirstColumn = true;
calculateText();
}
void ListerTextArea::sizeChanged()
{
if (_cursorAnchorPos > _lister->fileSize())
_cursorAnchorPos = -1;
if (_cursorPos > _lister->fileSize())
_cursorPos = _lister->fileSize();
redrawTextArea(true);
}
void ListerTextArea::resizeEvent(QResizeEvent * event)
{
KTextEdit::resizeEvent(event);
redrawTextArea();
}
void ListerTextArea::calculateText(const bool forcedUpdate)
{
const QRect contentRect = viewport()->contentsRect();
const QFontMetrics fm(font());
const int fontHeight = std::max(fm.height(), 1);
// This is quite accurate (although not perfect) way of getting
// a single character width along with its surrounding space.
const float fontWidth = (fm.width("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW") - fm.width("W")) / 99.0;
const int sizeY = contentRect.height() / fontHeight;
_pageSize = sizeY;
const int textViewportWidth = std::max(contentRect.width() - (int) fontWidth, 0);
setTabStopWidth(fontWidth * _tabWidth);
const int sizeX = textViewportWidth / fontWidth;
_sizeChanged = (_sizeY != sizeY) || (_sizeX != sizeX) || forcedUpdate;
_sizeY = sizeY;
_sizeX = sizeX;
QList rowStarts;
QStringList list = readLines(_screenStartPos, _screenEndPos, _sizeY, &rowStarts);
if (_sizeChanged) {
_averagePageSize = _screenEndPos - _screenStartPos;
setUpScrollBar();
}
const QStringList listRemn = readLines(_screenEndPos, _screenEndPos, 1);
list << listRemn;
if (list != _rowContent) {
_cursorBlinkMutex.lock();
_blinkTimer.stop();
setCursorWidth(0);
setPlainText(list.join("\n"));
if (_cursorAnchorPos == -1 || _cursorAnchorPos == _cursorPos) {
clearSelection();
_blinkTimer.start(500);
}
_cursorBlinkMutex.unlock();
_rowContent = list;
_rowStarts = rowStarts;
if (_rowStarts.size() < _sizeY) {
_rowStarts << _screenEndPos;
}
}
}
qint64 ListerTextArea::textToFilePositionOnScreen(const int x, const int y, bool &isfirst)
{
isfirst = (x == 0);
if (y >= _rowStarts.count()) {
return 0;
}
const qint64 rowStart = _rowStarts[ y ];
if (x == 0) {
return rowStart;
}
if (_hexMode) {
const qint64 pos = rowStart + _lister->hexPositionToIndex(_sizeX, x);
if (pos > _lister->fileSize()) {
return _lister->fileSize();
}
return pos;
}
// we can't use fromUnicode because of the invalid encoded chars
const int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH;
QByteArray chunk = _lister->cacheChunk(rowStart, maxBytes);
QTextStream stream(&chunk);
stream.setCodec(_lister->codec());
stream.read(x);
return rowStart + stream.pos();
}
void ListerTextArea::fileToTextPositionOnScreen(const qint64 p, const bool isfirst, int &x, int &y)
{
// check if cursor is outside of visible area
if (p < _screenStartPos || p > _screenEndPos || _rowStarts.count() < 1) {
x = -1;
y = (p > _screenEndPos) ? -2 : -1;
return;
}
// find row
y = 0;
while (y < _rowStarts.count() && _rowStarts[ y ] <= p) {
y++;
}
y--;
if (y < 0) {
x = y = -1;
return;
}
const qint64 rowStart = _rowStarts[ y ];
if (_hexMode) {
x = _lister->hexIndexToPosition(_sizeX, (int)(p - rowStart));
return;
}
// find column
const int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH;
x = 0;
if (rowStart >= p) {
if ((rowStart == p) && !isfirst && y > 0) {
const qint64 previousRow = _rowStarts[ y - 1 ];
const QByteArray chunk = _lister->cacheChunk(previousRow, maxBytes);
QByteArray cachedBuffer = chunk.left(p - previousRow);
QTextStream stream(&cachedBuffer);
stream.setCodec(_lister->codec());
stream.read(_rowContent[ y - 1].length());
if (previousRow + stream.pos() == p) {
y--;
x = _rowContent[ y ].length();
}
}
return;
}
const QByteArray chunk = _lister->cacheChunk(rowStart, maxBytes);
const QByteArray cachedBuffer = chunk.left(p - rowStart);
x = _lister->codec()->toUnicode(cachedBuffer).length();
}
void ListerTextArea::getCursorPosition(int &x, int &y)
{
getScreenPosition(textCursor().position(), x, y);
}
void ListerTextArea::getScreenPosition(const int position, int &x, int &y)
{
x = position;
y = 0;
foreach (const QString &row, _rowContent) {
const int rowLen = row.length() + 1;
if (x < rowLen) {
return;
}
x -= rowLen;
y++;
}
}
void ListerTextArea::setCursorPositionOnScreen(const int x, const int y, const int anchorX, const int anchorY)
{
setCursorWidth(0);
int finalX = x;
int finalY = y;
if (finalX == -1 || finalY < 0) {
if (anchorY == -1) {
return;
}
if (finalY == -2) {
finalY = _sizeY;
finalX = (_rowContent.count() > _sizeY) ? _rowContent[ _sizeY ].length() : 0;
} else
finalX = finalY = 0;
}
const int realSizeY = std::min(_sizeY + 1, _rowContent.count());
const auto setUpCursor = [&] (const int cursorX, const int cursorY, const QTextCursor::MoveMode mode) -> bool {
if (cursorY > realSizeY) {
return false;
}
_skipCursorChangedListener = true;
moveCursor(QTextCursor::Start, mode);
for (int i = 0; i < cursorY; i++) {
moveCursor(QTextCursor::Down, mode);
}
int finalCursorX = cursorX;
if (_rowContent.count() > cursorY && finalCursorX > _rowContent[ cursorY ].length()) {
finalCursorX = _rowContent[ cursorY ].length();
}
for (int i = 0; i < finalCursorX; i++) {
moveCursor(QTextCursor::Right, mode);
}
_skipCursorChangedListener = false;
return true;
};
QTextCursor::MoveMode mode = QTextCursor::MoveAnchor;
// set cursor anchor
if (anchorX != -1 && anchorY != -1) {
const bool canContinue = setUpCursor(anchorX, anchorY, mode);
if (!canContinue) {
return;
}
mode = QTextCursor::KeepAnchor;
}
// set cursor position
setUpCursor(finalX, finalY, mode);
}
qint64 ListerTextArea::getCursorPosition(bool &isfirst)
{
if (cursorWidth() == 0) {
isfirst = _cursorAtFirstColumn;
return _cursorPos;
}
int x, y;
getCursorPosition(x, y);
return textToFilePositionOnScreen(x, y, isfirst);
}
void ListerTextArea::setCursorPositionInDocument(const qint64 p, const bool isfirst)
{
_cursorPos = p;
int x, y;
fileToTextPositionOnScreen(p, isfirst, x, y);
bool startBlinkTimer = _screenStartPos <= _cursorPos && _cursorPos <= _screenEndPos;
int anchorX = -1, anchorY = -1;
if (_cursorAnchorPos != -1 && _cursorAnchorPos != p) {
int anchPos = _cursorAnchorPos;
bool anchorBelow = false, anchorAbove = false;
if (anchPos < _screenStartPos) {
anchPos = _screenStartPos;
anchorY = -2;
anchorAbove = true;
}
if (anchPos > _screenEndPos) {
anchPos = _screenEndPos;
anchorY = -3;
anchorBelow = true;
}
fileToTextPositionOnScreen(anchPos, isfirst, anchorX, anchorY);
if (_hexMode) {
if (anchorAbove) {
anchorX = 0;
}
if (anchorBelow && _rowContent.count() > 0) {
anchorX = _rowContent[ 0 ].length();
}
}
startBlinkTimer = startBlinkTimer && !anchorAbove && !anchorBelow;
}
if (startBlinkTimer) {
_blinkTimer.start(500);
}
setCursorPositionOnScreen(x, y, anchorX, anchorY);
_lister->slotUpdate();
}
void ListerTextArea::slotCursorPositionChanged()
{
if (_skipCursorChangedListener) {
return;
}
int cursorX, cursorY;
getCursorPosition(cursorX, cursorY);
_cursorAtFirstColumn = (cursorX == 0);
_cursorPos = textToFilePositionOnScreen(cursorX, cursorY, _cursorAtFirstColumn);
_lister->slotUpdate();
}
QString ListerTextArea::readSection(const qint64 p1, const qint64 p2)
{
if (p1 == p2)
return QString();
qint64 sel1 = p1;
qint64 sel2 = p2;
if (sel1 > sel2) {
std::swap(sel1, sel2);
}
QString section;
if (_hexMode) {
while (sel1 != sel2) {
const QStringList list = _lister->readHexLines(sel1, sel2, _sizeX, 1);
if (list.isEmpty()) {
break;
}
if (!section.isEmpty()) {
section += QChar('\n');
}
section += list.at(0);
}
return section;
}
qint64 pos = sel1;
QScopedPointer decoder(_lister->codec()->makeDecoder());
do {
const int maxBytes = std::min(_sizeX * _sizeY * MAX_CHAR_LENGTH, (int) (sel2 - pos));
const QByteArray chunk = _lister->cacheChunk(pos, maxBytes);
if (chunk.isEmpty())
break;
section += decoder->toUnicode(chunk);
pos += chunk.size();
} while (pos < sel2);
return section;
}
QStringList ListerTextArea::readLines(qint64 filePos, qint64 &endPos, const int lines, QList * locs)
{
QStringList list;
if (_hexMode) {
endPos = _lister->fileSize();
if (filePos >= endPos) {
return list;
}
const int bytes = _lister->hexBytesPerLine(_sizeX);
qint64 startPos = (filePos / bytes) * bytes;
qint64 shiftPos = startPos;
list = _lister->readHexLines(shiftPos, endPos, _sizeX, lines);
endPos = shiftPos;
if (locs) {
for (int i = 0; i < list.count(); i++) {
(*locs) << startPos;
startPos += bytes;
}
}
return list;
}
endPos = filePos;
const int maxBytes = _sizeX * _sizeY * MAX_CHAR_LENGTH;
const QByteArray chunk = _lister->cacheChunk(filePos, maxBytes);
if (chunk.isEmpty())
return list;
int byteCounter = 0;
QString row = "";
int effLength = 0;
if (locs)
(*locs) << filePos;
bool skipImmediateNewline = false;
const auto performNewline = [&] (qint64 nextRowStartOffset) {
list << row;
effLength = 0;
row = "";
if (locs) {
(*locs) << (filePos + nextRowStartOffset);
}
};
QScopedPointer decoder(_lister->codec()->makeDecoder());
while (byteCounter < chunk.size() && list.size() < lines) {
const int lastCnt = byteCounter;
QString chr = decoder->toUnicode(chunk.mid(byteCounter++, 1));
if (chr.isEmpty()) {
continue;
}
if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) {
chr = QChar(CONTROL_CHAR);
}
if (chr == "\n") {
if (!skipImmediateNewline) {
performNewline(byteCounter);
}
skipImmediateNewline = false;
continue;
}
skipImmediateNewline = false;
if (chr == "\t") {
effLength += _tabWidth - (effLength % _tabWidth) - 1;
if (effLength > _sizeX) {
performNewline(lastCnt);
}
}
row += chr;
effLength++;
if (effLength >= _sizeX) {
performNewline(byteCounter);
skipImmediateNewline = true;
}
}
if (list.size() < lines)
list << row;
endPos = filePos + byteCounter;
return list;
}
void ListerTextArea::setUpScrollBar()
{
if (_averagePageSize == _lister->fileSize()) {
_lister->scrollBar()->setPageStep(0);
_lister->scrollBar()->setMaximum(0);
_lister->scrollBar()->hide();
_lastPageStartPos = 0;
} else {
const int maxPage = MAX_CHAR_LENGTH * _sizeX * _sizeY;
qint64 pageStartPos = _lister->fileSize() - maxPage;
qint64 endPos;
if (pageStartPos < 0)
pageStartPos = 0;
QStringList list = readLines(pageStartPos, endPos, maxPage);
if (list.count() <= _sizeY) {
_lastPageStartPos = 0;
} else {
readLines(pageStartPos, _lastPageStartPos, list.count() - _sizeY);
}
const int maximum = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX : _lastPageStartPos;
int pageSize = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _averagePageSize / _lastPageStartPos : _averagePageSize;
if (pageSize == 0)
pageSize++;
_lister->scrollBar()->setPageStep(pageSize);
_lister->scrollBar()->setMaximum(maximum);
_lister->scrollBar()->show();
}
}
void ListerTextArea::keyPressEvent(QKeyEvent * ke)
{
if (KrGlobal::copyShortcut == QKeySequence(ke->key() | ke->modifiers())) {
copySelectedToClipboard();
ke->accept();
return;
}
if (ke->modifiers() == Qt::NoModifier || ke->modifiers() & Qt::ShiftModifier) {
qint64 newAnchor = -1;
if (ke->modifiers() & Qt::ShiftModifier) {
newAnchor = _cursorAnchorPos;
if (_cursorAnchorPos == -1)
newAnchor = _cursorPos;
}
switch (ke->key()) {
case Qt::Key_F3:
ke->accept();
if (ke->modifiers() == Qt::ShiftModifier)
_lister->searchPrev();
else
_lister->searchNext();
return;
case Qt::Key_Home:
case Qt::Key_End:
_cursorAnchorPos = newAnchor;
break;
case Qt::Key_Left: {
_cursorAnchorPos = newAnchor;
ensureVisibleCursor();
int x, y;
getCursorPosition(x, y);
if (y == 0 && x == 0)
slotActionTriggered(QAbstractSlider::SliderSingleStepSub);
}
break;
case Qt::Key_Right: {
_cursorAnchorPos = newAnchor;
ensureVisibleCursor();
if (textCursor().position() == toPlainText().length())
slotActionTriggered(QAbstractSlider::SliderSingleStepAdd);
}
break;
case Qt::Key_Up: {
_cursorAnchorPos = newAnchor;
ensureVisibleCursor();
int x, y;
getCursorPosition(x, y);
if (y == 0)
slotActionTriggered(QAbstractSlider::SliderSingleStepSub);
}
break;
case Qt::Key_Down: {
_cursorAnchorPos = newAnchor;
ensureVisibleCursor();
int x, y;
getCursorPosition(x, y);
if (y >= _sizeY-1)
slotActionTriggered(QAbstractSlider::SliderSingleStepAdd);
}
break;
case Qt::Key_PageDown: {
_cursorAnchorPos = newAnchor;
ensureVisibleCursor();
ke->accept();
int x, y;
getCursorPosition(x, y);
slotActionTriggered(QAbstractSlider::SliderPageStepAdd);
y += _sizeY - _skippedLines;
if (y > _rowContent.count()) {
y = _rowContent.count() - 1;
if (y > 0)
x = _rowContent[ y - 1 ].length();
else
x = 0;
}
_cursorPos = textToFilePositionOnScreen(x, y, _cursorAtFirstColumn);
setCursorPositionInDocument(_cursorPos, _cursorAtFirstColumn);
}
return;
case Qt::Key_PageUp: {
_cursorAnchorPos = newAnchor;
ensureVisibleCursor();
ke->accept();
int x, y;
getCursorPosition(x, y);
slotActionTriggered(QAbstractSlider::SliderPageStepSub);
y -= _sizeY - _skippedLines;
if (y < 0) {
y = 0;
x = 0;
}
_cursorPos = textToFilePositionOnScreen(x, y, _cursorAtFirstColumn);
setCursorPositionInDocument(_cursorPos, _cursorAtFirstColumn);
}
return;
}
}
if (ke->modifiers() == Qt::ControlModifier) {
switch (ke->key()) {
case Qt::Key_G:
ke->accept();
_lister->jumpToPosition();
return;
case Qt::Key_F:
ke->accept();
_lister->enableSearch(true);
return;
case Qt::Key_Home:
_cursorAnchorPos = -1;
ke->accept();
slotActionTriggered(QAbstractSlider::SliderToMinimum);
setCursorPositionInDocument((qint64)0, true);
return;
case Qt::Key_A:
case Qt::Key_End: {
_cursorAnchorPos = (ke->key() == Qt::Key_A) ? 0 : -1;
ke->accept();
slotActionTriggered(QAbstractSlider::SliderToMaximum);
const qint64 endPos = _lister->fileSize();
setCursorPositionInDocument(endPos, false);
return;
}
case Qt::Key_Down:
ke->accept();
slotActionTriggered(QAbstractSlider::SliderSingleStepAdd);
return;
case Qt::Key_Up:
ke->accept();
slotActionTriggered(QAbstractSlider::SliderSingleStepSub);
return;
case Qt::Key_PageDown:
ke->accept();
slotActionTriggered(QAbstractSlider::SliderPageStepAdd);
return;
case Qt::Key_PageUp:
ke->accept();
slotActionTriggered(QAbstractSlider::SliderPageStepSub);
return;
}
}
const int oldAnchor = textCursor().anchor();
KTextEdit::keyPressEvent(ke);
handleAnchorChange(oldAnchor);
}
void ListerTextArea::mousePressEvent(QMouseEvent * e)
{
KTextEdit::mousePressEvent(e);
// do change anchor only when shift is not pressed
if (!(QGuiApplication::keyboardModifiers() & Qt::ShiftModifier)) {
performAnchorChange(textCursor().anchor());
}
}
void ListerTextArea::mouseDoubleClickEvent(QMouseEvent * e)
{
_cursorAnchorPos = -1;
const int oldAnchor = textCursor().anchor();
KTextEdit::mouseDoubleClickEvent(e);
handleAnchorChange(oldAnchor);
}
void ListerTextArea::mouseMoveEvent(QMouseEvent * e)
{
if (e->pos().y() < 0) {
slotActionTriggered(QAbstractSlider::SliderSingleStepSub);
} else if (e->pos().y() > height()) {
slotActionTriggered(QAbstractSlider::SliderSingleStepAdd);
}
KTextEdit::mouseMoveEvent(e);
}
void ListerTextArea::wheelEvent(QWheelEvent * e)
{
int delta = e->delta();
if (delta) {
// zooming
if (e->modifiers() & Qt::ControlModifier) {
e->accept();
if (delta > 0) {
zoomIn();
} else {
zoomOut();
}
return;
}
if (delta > 0) {
e->accept();
while (delta > 0) {
slotActionTriggered(QAbstractSlider::SliderSingleStepSub);
slotActionTriggered(QAbstractSlider::SliderSingleStepSub);
slotActionTriggered(QAbstractSlider::SliderSingleStepSub);
delta -= 120;
}
} else {
e->accept();
while (delta < 0) {
slotActionTriggered(QAbstractSlider::SliderSingleStepAdd);
slotActionTriggered(QAbstractSlider::SliderSingleStepAdd);
slotActionTriggered(QAbstractSlider::SliderSingleStepAdd);
delta += 120;
}
}
setCursorPositionInDocument(_cursorPos, false);
}
}
void ListerTextArea::slotActionTriggered(int action)
{
switch (action) {
case QAbstractSlider::SliderSingleStepAdd: {
qint64 endPos;
readLines(_screenStartPos, endPos, 1);
if (endPos <= _lastPageStartPos) {
_screenStartPos = endPos;
}
}
break;
case QAbstractSlider::SliderSingleStepSub: {
if (_screenStartPos == 0) {
break;
}
if (_hexMode) {
int bytesPerRow = _lister->hexBytesPerLine(_sizeX);
_screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow;
_screenStartPos -= bytesPerRow;
if (_screenStartPos < 0) {
_screenStartPos = 0;
}
break;
}
int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH;
const QByteArray encodedEnter = _lister->codec()->fromUnicode(QString("\n"));
qint64 readPos = _screenStartPos - maxSize;
if (readPos < 0) {
readPos = 0;
}
maxSize = _screenStartPos - readPos;
const QByteArray chunk = _lister->cacheChunk(readPos, maxSize);
int from = chunk.size();
while (from > 0) {
from--;
from = chunk.lastIndexOf(encodedEnter, from);
if (from == -1) {
from = 0;
break;
}
const int backRef = std::max(from - 20, 0);
const int size = from - backRef + encodedEnter.size();
const QString decoded = _lister->codec()->toUnicode(chunk.mid(backRef, size));
if (decoded.endsWith(QLatin1String("\n"))) {
if (from < (chunk.size() - encodedEnter.size())) {
from += encodedEnter.size();
break;
}
}
}
readPos += from;
qint64 previousPos = readPos;
while (readPos < _screenStartPos) {
previousPos = readPos;
readLines(readPos, readPos, 1);
}
_screenStartPos = previousPos;
}
break;
case QAbstractSlider::SliderPageStepAdd: {
_skippedLines = 0;
qint64 endPos;
for (int i = 0; i < _sizeY; i++) {
readLines(_screenStartPos, endPos, 1);
if (endPos <= _lastPageStartPos) {
_screenStartPos = endPos;
_skippedLines++;
} else {
break;
}
}
}
break;
case QAbstractSlider::SliderPageStepSub: {
_skippedLines = 0;
if (_screenStartPos == 0) {
break;
}
if (_hexMode) {
const int bytesPerRow = _lister->hexBytesPerLine(_sizeX);
_screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow;
_screenStartPos -= _sizeY * bytesPerRow;
if (_screenStartPos < 0) {
_screenStartPos = 0;
}
break;
}
// text lister mode
int maxSize = 2 * _sizeX * _sizeY * MAX_CHAR_LENGTH;
const QByteArray encodedEnter = _lister->codec()->fromUnicode(QString("\n"));
qint64 readPos = _screenStartPos - maxSize;
if (readPos < 0)
readPos = 0;
maxSize = _screenStartPos - readPos;
const QByteArray chunk = _lister->cacheChunk(readPos, maxSize);
maxSize = chunk.size();
int sizeY = _sizeY + 1;
int origSizeY = sizeY;
int from = maxSize;
int lastEnter = maxSize;
bool readNext = true;
while (readNext) {
readNext = false;
while (from > 0) {
from--;
from = chunk.lastIndexOf(encodedEnter, from);
if (from == -1) {
from = 0;
break;
}
const int backRef = std::max(from - 20, 0);
const int size = from - backRef + encodedEnter.size();
QString decoded = _lister->codec()->toUnicode(chunk.mid(backRef, size));
if (decoded.endsWith(QLatin1String("\n"))) {
if (from < (maxSize - encodedEnter.size())) {
int arrayStart = from + encodedEnter.size();
decoded = _lister->codec()->toUnicode(chunk.mid(arrayStart, lastEnter - arrayStart));
sizeY -= ((decoded.length() / (_sizeX + 1)) + 1);
if (sizeY < 0) {
from = arrayStart;
break;
}
}
lastEnter = from;
}
}
qint64 searchPos = readPos + from;
QList locs;
while (searchPos < _screenStartPos) {
locs << searchPos;
readLines(searchPos, searchPos, 1);
}
if (locs.count() >= _sizeY) {
_screenStartPos = locs[ locs.count() - _sizeY ];
} else if (from != 0) {
origSizeY += locs.count() + 1;
sizeY = origSizeY;
readNext = true;
} else if (readPos == 0) {
_screenStartPos = 0;
}
}
}
break;
case QAbstractSlider::SliderToMinimum:
_screenStartPos = 0;
break;
case QAbstractSlider::SliderToMaximum:
_screenStartPos = _lastPageStartPos;
break;
case QAbstractSlider::SliderMove: {
if (_inSliderOp) // self created call?
return;
qint64 pos = _lister->scrollBar()->sliderPosition();
if (pos == SLIDER_MAX) {
_screenStartPos = _lastPageStartPos;
break;
} else if (pos == 0) {
_screenStartPos = 0;
break;
}
if (_lastPageStartPos > SLIDER_MAX)
pos = _lastPageStartPos * pos / SLIDER_MAX;
if (pos != 0) {
if (_hexMode) {
const int bytesPerRow = _lister->hexBytesPerLine(_sizeX);
pos = (pos / bytesPerRow) * bytesPerRow;
} else {
const int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH;
qint64 readPos = pos - maxSize;
if (readPos < 0)
readPos = 0;
qint64 previousPos = readPos;
while (readPos <= pos) {
previousPos = readPos;
readLines(readPos, readPos, 1);
}
pos = previousPos;
}
}
_screenStartPos = pos;
}
break;
case QAbstractSlider::SliderNoAction:
break;
};
_inSliderOp = true;
const int value = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _screenStartPos / _lastPageStartPos : _screenStartPos;
_lister->scrollBar()->setSliderPosition(value);
_inSliderOp = false;
redrawTextArea();
}
void ListerTextArea::redrawTextArea(bool forcedUpdate)
{
if (_redrawing) {
return;
}
_redrawing = true;
bool isfirst;
const qint64 pos = getCursorPosition(isfirst);
calculateText(forcedUpdate);
setCursorPositionInDocument(pos, isfirst);
_redrawing = false;
}
void ListerTextArea::ensureVisibleCursor()
{
if (_screenStartPos <= _cursorPos && _cursorPos <= _screenEndPos) {
return;
}
int delta = _sizeY / 2;
if (delta == 0)
delta++;
qint64 newScreenStart = _cursorPos;
while (delta) {
const int maxSize = _sizeX * MAX_CHAR_LENGTH;
qint64 readPos = newScreenStart - maxSize;
if (readPos < 0)
readPos = 0;
qint64 previousPos = readPos;
while (readPos < newScreenStart) {
previousPos = readPos;
readLines(readPos, readPos, 1);
if (readPos == previousPos)
break;
}
newScreenStart = previousPos;
delta--;
}
if (newScreenStart > _lastPageStartPos) {
newScreenStart = _lastPageStartPos;
}
_screenStartPos = newScreenStart;
slotActionTriggered(QAbstractSlider::SliderNoAction);
}
void ListerTextArea::setAnchorAndCursor(qint64 anchor, qint64 cursor)
{
_cursorPos = cursor;
_cursorAnchorPos = anchor;
ensureVisibleCursor();
setCursorPositionInDocument(cursor, false);
}
QString ListerTextArea::getSelectedText()
{
if (_cursorAnchorPos != -1 && _cursorAnchorPos != _cursorPos) {
return readSection(_cursorAnchorPos, _cursorPos);
}
return QString();
}
void ListerTextArea::copySelectedToClipboard()
{
const QString selection = getSelectedText();
if (!selection.isEmpty()) {
QApplication::clipboard()->setText(selection);
}
}
void ListerTextArea::clearSelection()
{
QTextCursor cursor = textCursor();
cursor.clearSelection();
setTextCursor(cursor);
_cursorAnchorPos = -1;
}
void ListerTextArea::performAnchorChange(int anchor)
{
int x, y;
bool isfirst;
getScreenPosition(anchor, x, y);
_cursorAnchorPos = textToFilePositionOnScreen(x, y, isfirst);
}
void ListerTextArea::handleAnchorChange(int oldAnchor)
{
const int anchor = textCursor().anchor();
if (oldAnchor != anchor) {
performAnchorChange(anchor);
}
}
void ListerTextArea::setHexMode(bool hexMode)
{
bool isfirst;
const qint64 pos = getCursorPosition(isfirst);
_hexMode = hexMode;
_screenStartPos = 0;
calculateText(true);
setCursorPositionInDocument(pos, isfirst);
ensureVisibleCursor();
}
void ListerTextArea::zoomIn(int range)
{
KTextEdit::zoomIn(range);
redrawTextArea();
}
void ListerTextArea::zoomOut(int range)
{
KTextEdit::zoomOut(range);
redrawTextArea();
}
ListerPane::ListerPane(Lister *lister, QWidget *parent) : QWidget(parent), _lister(lister)
{
}
bool ListerPane::event(QEvent *e)
{
const bool handled = ListerPane::handleCloseEvent(e);
if (!handled) {
return QWidget::event(e);
}
return true;
}
bool ListerPane::handleCloseEvent(QEvent *e)
{
if (e->type() == QEvent::ShortcutOverride) {
QKeyEvent *ke = static_cast(e);
if (ke->key() == Qt::Key_Escape) {
if (_lister->isSearchEnabled()) {
_lister->searchDelete();
_lister->enableSearch(false);
ke->accept();
return true;
}
if (!_lister->textArea()->getSelectedText().isEmpty()) {
_lister->textArea()->clearSelection();
ke->accept();
return true;
}
}
}
return false;
}
ListerBrowserExtension::ListerBrowserExtension(Lister * lister) : KParts::BrowserExtension(lister)
{
_lister = lister;
emit enableAction("copy", true);
emit enableAction("print", true);
}
void ListerBrowserExtension::copy()
{
_lister->textArea()->copySelectedToClipboard();
}
void ListerBrowserExtension::print()
{
_lister->print();
}
class ListerEncodingMenu : public KrRemoteEncodingMenu
{
public:
ListerEncodingMenu(Lister *lister, const QString &text, const QString &icon, KActionCollection *parent) :
KrRemoteEncodingMenu(text, icon, parent), _lister(lister) {
}
protected:
virtual QString currentCharacterSet() Q_DECL_OVERRIDE {
return _lister->characterSet();
}
virtual void chooseDefault() Q_DECL_OVERRIDE {
_lister->setCharacterSet(QString());
}
virtual void chooseEncoding(QString encodingName) Q_DECL_OVERRIDE {
QString charset = KCharsets::charsets()->encodingForName(encodingName);
_lister->setCharacterSet(charset);
}
Lister * _lister;
};
Lister::Lister(QWidget *parent) : KParts::ReadOnlyPart(parent)
{
setXMLFile("krusaderlisterui.rc");
_actionSaveSelected = new QAction(Icon("document-save"), i18n("Save selection..."), this);
connect(_actionSaveSelected, &QAction::triggered, this, &Lister::saveSelected);
actionCollection()->addAction("save_selected", _actionSaveSelected);
_actionSaveAs = new QAction(Icon("document-save-as"), i18n("Save as..."), this);
connect(_actionSaveAs, &QAction::triggered, this, &Lister::saveAs);
actionCollection()->addAction("save_as", _actionSaveAs);
_actionPrint = new QAction(Icon("document-print"), i18n("Print..."), this);
connect(_actionPrint, &QAction::triggered, this, &Lister::print);
actionCollection()->addAction("print", _actionPrint);
actionCollection()->setDefaultShortcut(_actionPrint, Qt::CTRL + Qt::Key_P);
_actionSearch = new QAction(Icon("system-search"), i18n("Search"), this);
connect(_actionSearch, &QAction::triggered, this, &Lister::searchAction);
actionCollection()->addAction("search", _actionSearch);
actionCollection()->setDefaultShortcut(_actionSearch, Qt::CTRL + Qt::Key_F);
_actionSearchNext = new QAction(Icon("go-down"), i18n("Search next"), this);
connect(_actionSearchNext, &QAction::triggered, this, &Lister::searchNext);
actionCollection()->addAction("search_next", _actionSearchNext);
actionCollection()->setDefaultShortcut(_actionSearchNext, Qt::Key_F3);
_actionSearchPrev = new QAction(Icon("go-up"), i18n("Search previous"), this);
connect(_actionSearchPrev, &QAction::triggered, this, &Lister::searchPrev);
actionCollection()->addAction("search_prev", _actionSearchPrev);
actionCollection()->setDefaultShortcut(_actionSearchPrev, Qt::SHIFT + Qt::Key_F3);
_actionJumpToPosition = new QAction(Icon("go-jump"), i18n("Jump to position"), this);
connect(_actionJumpToPosition, &QAction::triggered, this, &Lister::jumpToPosition);
actionCollection()->addAction("jump_to_position", _actionJumpToPosition);
actionCollection()->setDefaultShortcut(_actionJumpToPosition, Qt::CTRL + Qt::Key_G);
_actionHexMode = new QAction(Icon("document-preview"), i18n("Hex mode"), this);
connect(_actionHexMode, &QAction::triggered, this, &Lister::toggleHexMode);
actionCollection()->addAction("hex_mode", _actionHexMode);
actionCollection()->setDefaultShortcut(_actionHexMode, Qt::CTRL + Qt::Key_H);
new ListerEncodingMenu(this, i18n("Select charset"), "character-set", actionCollection());
QWidget * widget = new ListerPane(this, parent);
widget->setFocusPolicy(Qt::StrongFocus);
QGridLayout *grid = new QGridLayout(widget);
_textArea = new ListerTextArea(this, widget);
_textArea->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
_textArea->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
_textArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
_textArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
widget->setFocusProxy(_textArea);
grid->addWidget(_textArea, 0, 0);
_scrollBar = new QScrollBar(Qt::Vertical, widget);
grid->addWidget(_scrollBar, 0, 1);
_scrollBar->hide();
QWidget * statusWidget = new QWidget(widget);
QHBoxLayout *hbox = new QHBoxLayout(statusWidget);
_listerLabel = new QLabel(i18n("Lister:"), statusWidget);
hbox->addWidget(_listerLabel);
_searchProgressBar = new QProgressBar(statusWidget);
_searchProgressBar->setMinimum(0);
_searchProgressBar->setMaximum(1000);
_searchProgressBar->setValue(0);
_searchProgressBar->hide();
hbox->addWidget(_searchProgressBar);
_searchStopButton = new QToolButton(statusWidget);
_searchStopButton->setIcon(Icon("process-stop"));
_searchStopButton->setToolTip(i18n("Stop search"));
_searchStopButton->hide();
connect(_searchStopButton, &QToolButton::clicked, this, &Lister::searchDelete);
hbox->addWidget(_searchStopButton);
_searchLineEdit = new KLineEdit(statusWidget);
_searchLineEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
_originalBackground = _searchLineEdit->palette().color(QPalette::Base);
_originalForeground = _searchLineEdit->palette().color(QPalette::Text);
connect(_searchLineEdit, &KLineEdit::returnPressed, this, &Lister::searchNext);
connect(_searchLineEdit, &KLineEdit::textChanged, this, &Lister::searchTextChanged);
hbox->addWidget(_searchLineEdit);
_searchNextButton = new QPushButton(Icon("go-down"), i18n("Next"), statusWidget);
_searchNextButton->setToolTip(i18n("Jump to next match"));
connect(_searchNextButton, &QPushButton::clicked, this, &Lister::searchNext);
hbox->addWidget(_searchNextButton);
_searchPrevButton = new QPushButton(Icon("go-up"), i18n("Previous"), statusWidget);
_searchPrevButton->setToolTip(i18n("Jump to previous match"));
connect(_searchPrevButton, &QPushButton::clicked, this, &Lister::searchPrev);
hbox->addWidget(_searchPrevButton);
_searchOptions = new QPushButton(i18n("Options"), statusWidget);
_searchOptions->setToolTip(i18n("Modify search behavior"));
QMenu * menu = new QMenu();
_fromCursorAction = menu->addAction(i18n("From cursor"));
_fromCursorAction->setCheckable(true);
_fromCursorAction->setChecked(true);
_caseSensitiveAction = menu->addAction(i18n("Case sensitive"));
_caseSensitiveAction->setCheckable(true);
_matchWholeWordsOnlyAction = menu->addAction(i18n("Match whole words only"));
_matchWholeWordsOnlyAction->setCheckable(true);
_regExpAction = menu->addAction(i18n("RegExp"));
_regExpAction->setCheckable(true);
_hexAction = menu->addAction(i18n("Hexadecimal"));
_hexAction->setCheckable(true);
_searchOptions->setMenu(menu);
hbox->addWidget(_searchOptions);
hbox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
_statusLabel = new QLabel(statusWidget);
hbox->addWidget(_statusLabel);
grid->addWidget(statusWidget, 1, 0, 1, 2);
setWidget(widget);
- connect(_scrollBar, SIGNAL(actionTriggered(int)), _textArea, SLOT(slotActionTriggered(int)));
+ connect(_scrollBar, &QScrollBar::actionTriggered, _textArea, &ListerTextArea::slotActionTriggered);
connect(&_searchUpdateTimer, &QTimer::timeout, this, &Lister::slotUpdate);
new ListerBrowserExtension(this);
enableSearch(false);
_tempFile = new QTemporaryFile(this);
_tempFile->setFileTemplate(QDir::tempPath() + QLatin1String("/krusader_lister.XXXXXX"));
}
bool Lister::openUrl(const QUrl &listerUrl)
{
_downloading = false;
setUrl(listerUrl);
_fileSize = 0;
if (listerUrl.isLocalFile()) {
_filePath = listerUrl.path();
if (!QFile::exists(_filePath))
return false;
_fileSize = getFileSize();
} else {
if (_tempFile->isOpen()) {
_tempFile->close();
}
_tempFile->open();
_filePath = _tempFile->fileName();
KIO::TransferJob *downloadJob = KIO::get(listerUrl, KIO::NoReload, KIO::HideProgressInfo);
connect(downloadJob, &KIO::TransferJob::data, this, [=](KIO::Job*, QByteArray array) {
if (array.size() != 0) {
_tempFile->write(array);
} });
connect(downloadJob, &KIO::TransferJob::result, this, [=](KJob *job) {
_tempFile->flush();
if (job->error()) { /* any error occurred? */
KIO::TransferJob *kioJob = (KIO::TransferJob *)job;
KMessageBox::error(_textArea, i18n("Error reading file %1.", kioJob->url().toDisplayString(QUrl::PreferLocalFile)));
}
_downloading = false;
_downloadUpdateTimer.stop();
slotUpdate();
});
connect(&_downloadUpdateTimer, &QTimer::timeout, this, [&]() {
slotUpdate();
});
_downloadUpdateTimer.start(500);
_downloading = true;
}
// invalidate cache
_cache.clear();
_textArea->reset();
emit started(0);
emit setWindowCaption(listerUrl.toDisplayString());
emit completed();
return true;
}
QByteArray Lister::cacheChunk(const qint64 filePos, const int maxSize)
{
if (filePos >= _fileSize) {
return QByteArray();
}
int size = maxSize;
if (_fileSize - filePos < size) {
size = _fileSize - filePos;
}
if (!_cache.isEmpty() && (filePos >= _cachePos) && (filePos + size <= _cachePos + _cache.size())) {
return _cache.mid(filePos - _cachePos, size);
}
const int negativeOffset = CACHE_SIZE * 2 / 5;
qint64 cachePos = filePos - negativeOffset;
if (cachePos < 0)
cachePos = 0;
QFile sourceFile(_filePath);
if (!sourceFile.open(QIODevice::ReadOnly)) {
return QByteArray();
}
if (!sourceFile.seek(cachePos)) {
return QByteArray();
}
const QByteArray bytes = sourceFile.read(CACHE_SIZE);
if (bytes.isEmpty()) {
return bytes;
}
_cache = bytes;
_cachePos = cachePos;
const qint64 cacheRefIndex = filePos - _cachePos;
int newSize = bytes.size() - cacheRefIndex;
if (newSize < size)
size = newSize;
return _cache.mid(cacheRefIndex, size);
}
qint64 Lister::getFileSize()
{
return QFile(_filePath).size();
}
void Lister::guiActivateEvent(KParts::GUIActivateEvent * event)
{
if (event->activated()) {
slotUpdate();
_textArea->redrawTextArea(true);
} else {
enableSearch(false);
}
KParts::ReadOnlyPart::guiActivateEvent(event);
}
void Lister::slotUpdate()
{
const qint64 oldSize = _fileSize;
_fileSize = getFileSize();
if (oldSize != _fileSize)
_textArea->sizeChanged();
int cursorX = 0, cursorY = 0;
_textArea->getCursorPosition(cursorX, cursorY);
bool isfirst = false;
const qint64 cursor = _textArea->getCursorPosition(isfirst);
const int percent = (_fileSize == 0) ? 0 : (int)((201 * cursor) / _fileSize / 2);
const QString status = i18n("Column: %1, Position: %2 (%3, %4%)", cursorX, cursor, _fileSize, percent);
_statusLabel->setText(status);
if (_searchProgressCounter)
_searchProgressCounter--;
}
bool Lister::isSearchEnabled()
{
return !_searchLineEdit->isHidden() || !_searchProgressBar->isHidden();
}
void Lister::enableSearch(const bool enable)
{
if (enable) {
_listerLabel->setText(i18n("Search:"));
_searchLineEdit->show();
_searchNextButton->show();
_searchPrevButton->show();
_searchOptions->show();
if (!_searchLineEdit->hasFocus()) {
_searchLineEdit->setFocus();
const QString selection = _textArea->getSelectedText();
if (!selection.isEmpty()) {
_searchLineEdit->setText(selection);
}
_searchLineEdit->selectAll();
}
} else {
_listerLabel->setText(i18n("Lister:"));
_searchLineEdit->hide();
_searchNextButton->hide();
_searchPrevButton->hide();
_searchOptions->hide();
_textArea->setFocus();
}
}
void Lister::searchNext()
{
search(true);
}
void Lister::searchPrev()
{
search(false);
}
void Lister::search(const bool forward, const bool restart)
{
_restartFromBeginning = restart;
if (_searchInProgress || _searchLineEdit->text().isEmpty())
return;
if (_searchLineEdit->isHidden())
enableSearch(true);
_searchPosition = forward ? 0 : _fileSize;
if (_fromCursorAction->isChecked()) {
bool isfirst;
qint64 cursor = _textArea->getCursorPosition(isfirst);
if (cursor != 0 && !forward)
cursor--;
if (_searchLastFailedPosition == -1 || _searchLastFailedPosition != cursor)
_searchPosition = cursor;
}
const bool caseSensitive = _caseSensitiveAction->isChecked();
const bool matchWholeWord = _matchWholeWordsOnlyAction->isChecked();
const bool regExp = _regExpAction->isChecked();
const bool hex = _hexAction->isChecked();
if (hex) {
QString hexcontent = _searchLineEdit->text();
hexcontent.remove(QLatin1String("0x"));
hexcontent.remove(' ');
hexcontent.remove('\t');
hexcontent.remove('\n');
hexcontent.remove('\r');
_searchHexQuery = QByteArray();
if (hexcontent.length() & 1) {
setColor(false, false);
return;
}
while (!hexcontent.isEmpty()) {
const QString hexData = hexcontent.left(2);
hexcontent = hexcontent.mid(2);
bool ok = true;
const int c = hexData.toUInt(&ok, 16);
if (!ok) {
setColor(false, false);
return;
}
_searchHexQuery.push_back((char) c);
}
} else {
_searchQuery.setContent(_searchLineEdit->text(), caseSensitive, matchWholeWord, codec()->name(), regExp);
}
_searchIsForward = forward;
_searchHexadecimal = hex;
- QTimer::singleShot(0, this, SLOT(slotSearchMore()));
+ QTimer::singleShot(0, this, &Lister::slotSearchMore);
_searchInProgress = true;
_searchProgressCounter = 3;
enableActions(false);
}
void Lister::enableActions(const bool state)
{
_actionSearch->setEnabled(state);
_actionSearchNext->setEnabled(state);
_actionSearchPrev->setEnabled(state);
_actionJumpToPosition->setEnabled(state);
if (state) {
_searchUpdateTimer.stop();
} else {
slotUpdate();
}
}
void Lister::slotSearchMore()
{
if (!_searchInProgress)
return;
if (!_searchUpdateTimer.isActive()) {
_searchUpdateTimer.start(200);
}
updateProgressBar();
if (!_searchIsForward)
_searchPosition--;
if (_searchPosition < 0 || _searchPosition >= _fileSize) {
if (_restartFromBeginning)
resetSearchPosition();
else {
searchFailed();
return;
}
}
int maxCacheSize = SEARCH_CACHE_CHARS;
qint64 searchPos = _searchPosition;
bool setPosition = true;
if (!_searchIsForward) {
qint64 origSearchPos = _searchPosition;
searchPos -= maxCacheSize;
if (searchPos <= 0) {
searchPos = 0;
_searchPosition = 0;
setPosition = false;
}
qint64 diff = origSearchPos - searchPos;
if (diff < maxCacheSize)
maxCacheSize = diff;
}
const QByteArray chunk = cacheChunk(searchPos, maxCacheSize);
if (chunk.isEmpty()) {
searchFailed();
return;
}
const int chunkSize = chunk.size();
qint64 foundAnchor = -1;
qint64 foundCursor = -1;
int byteCounter = 0;
if (_searchHexadecimal) {
const int ndx = _searchIsForward ? chunk.indexOf(_searchHexQuery) : chunk.lastIndexOf(_searchHexQuery);
if (chunkSize > _searchHexQuery.length()) {
if (_searchIsForward) {
_searchPosition = searchPos + chunkSize;
if ((_searchPosition < _fileSize) && (chunkSize > _searchHexQuery.length()))
_searchPosition -= _searchHexQuery.length();
byteCounter = _searchPosition - searchPos;
} else {
if (_searchPosition > 0)
_searchPosition += _searchHexQuery.length();
}
}
if (ndx != -1) {
foundAnchor = searchPos + ndx;
foundCursor = foundAnchor + _searchHexQuery.length();
}
} else {
int rowStart = 0;
QString row = "";
QScopedPointer decoder(_codec->makeDecoder());
while (byteCounter < chunkSize) {
const QString chr = decoder->toUnicode(chunk.mid(byteCounter++, 1));
if (chr.isEmpty() && byteCounter < chunkSize) {
continue;
}
if (chr != "\n")
row += chr;
if (chr == "\n" || row.length() >= SEARCH_MAX_ROW_LEN || byteCounter >= chunkSize) {
if (setPosition) {
_searchPosition = searchPos + byteCounter;
if (!_searchIsForward) {
_searchPosition++;
setPosition = false;
}
}
if (_searchQuery.checkLine(row, !_searchIsForward)) {
QByteArray cachedBuffer = chunk.mid(rowStart, chunkSize - rowStart);
QTextStream stream(&cachedBuffer);
stream.setCodec(_codec);
stream.read(_searchQuery.matchIndex());
foundAnchor = searchPos + rowStart + stream.pos();
stream.read(_searchQuery.matchLength());
foundCursor = searchPos + rowStart + stream.pos();
if (_searchIsForward)
break;
}
row = "";
rowStart = byteCounter;
}
}
}
if (foundAnchor != -1 && foundCursor != -1) {
_textArea->setAnchorAndCursor(foundAnchor, foundCursor);
searchSucceeded();
return;
}
if (_searchIsForward && searchPos + byteCounter >= _fileSize) {
if (_restartFromBeginning)
resetSearchPosition();
else {
searchFailed();
return;
}
} else if (_searchPosition <= 0 || _searchPosition >= _fileSize) {
if (_restartFromBeginning)
resetSearchPosition();
else {
searchFailed();
return;
}
}
- QTimer::singleShot(0, this, SLOT(slotSearchMore()));
+ QTimer::singleShot(0, this, &Lister::slotSearchMore);
}
void Lister::resetSearchPosition()
{
_restartFromBeginning = false;
_searchPosition = _searchIsForward ? 0 : _fileSize - 1;
}
void Lister::searchSucceeded()
{
_searchInProgress = false;
setColor(true, false);
hideProgressBar();
_searchLastFailedPosition = -1;
enableActions(true);
}
void Lister::searchFailed()
{
_searchInProgress = false;
setColor(false, false);
hideProgressBar();
bool isfirst;
_searchLastFailedPosition = _textArea->getCursorPosition(isfirst);
if (!_searchIsForward)
_searchLastFailedPosition--;
enableActions(true);
}
void Lister::searchDelete()
{
_searchInProgress = false;
setColor(false, true);
hideProgressBar();
_searchLastFailedPosition = -1;
enableActions(true);
}
void Lister::searchTextChanged()
{
searchDelete();
if (_fileSize < 0x10000) { // autosearch files less than 64k
if (!_searchLineEdit->text().isEmpty()) {
bool isfirst;
const qint64 anchor = _textArea->getCursorAnchor();
const qint64 cursor = _textArea->getCursorPosition(isfirst);
if (cursor > anchor && anchor != -1) {
_textArea->setCursorPositionInDocument(anchor, true);
}
search(true, true);
}
}
}
void Lister::setColor(const bool match, const bool restore)
{
QColor fore, back;
if (!restore) {
const KConfigGroup gc(krConfig, "Colors");
QString foreground, background;
const QPalette p = QGuiApplication::palette();
if (match) {
foreground = "Quicksearch Match Foreground";
background = "Quicksearch Match Background";
fore = Qt::black;
back = QColor(192, 255, 192);
} else {
foreground = "Quicksearch Non-match Foreground";
background = "Quicksearch Non-match Background";
fore = Qt::black;
back = QColor(255, 192, 192);
}
if (gc.readEntry(foreground, QString()) == "KDE default")
fore = p.color(QPalette::Active, QPalette::Text);
else if (!gc.readEntry(foreground, QString()).isEmpty())
fore = gc.readEntry(foreground, fore);
if (gc.readEntry(background, QString()) == "KDE default")
back = p.color(QPalette::Active, QPalette::Base);
else if (!gc.readEntry(background, QString()).isEmpty())
back = gc.readEntry(background, back);
} else {
back = _originalBackground;
fore = _originalForeground;
}
QPalette pal = _searchLineEdit->palette();
pal.setColor(QPalette::Base, back);
pal.setColor(QPalette::Text, fore);
_searchLineEdit->setPalette(pal);
}
void Lister::hideProgressBar()
{
if (!_searchProgressBar->isHidden()) {
_searchProgressBar->hide();
_searchStopButton->hide();
_searchLineEdit->show();
_searchNextButton->show();
_searchPrevButton->show();
_searchOptions->show();
_listerLabel->setText(i18n("Search:"));
}
}
void Lister::updateProgressBar()
{
if (_searchProgressCounter)
return;
if (_searchProgressBar->isHidden()) {
_searchProgressBar->show();
_searchStopButton->show();
_searchOptions->hide();
_searchLineEdit->hide();
_searchNextButton->hide();
_searchPrevButton->hide();
_listerLabel->setText(i18n("Search position:"));
// otherwise focus is set to document tab
_textArea->setFocus();
}
const qint64 pcnt = (_fileSize == 0) ? 1000 : (2001 * _searchPosition) / _fileSize / 2;
const int pctInt = (int) pcnt;
if (_searchProgressBar->value() != pctInt)
_searchProgressBar->setValue(pctInt);
}
void Lister::jumpToPosition()
{
bool ok = true;
QString res = QInputDialog::getText(_textArea, i18n("Jump to position"), i18n("Text position:"),
QLineEdit::Normal, "0", &ok);
if (!ok)
return;
res = res.trimmed();
qint64 pos = -1;
if (res.startsWith(QLatin1String("0x"))) {
res = res.mid(2);
bool ok;
const qulonglong upos = res.toULongLong(&ok, 16);
if (!ok) {
KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position"));
return;
}
pos = (qint64)upos;
} else {
bool ok;
const qulonglong upos = res.toULongLong(&ok);
if (!ok) {
KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position"));
return;
}
pos = (qint64)upos;
}
if (pos < 0 || pos > _fileSize) {
KMessageBox::error(_textArea, i18n("Number out of range."), i18n("Jump to position"));
return;
}
_textArea->deleteAnchor();
_textArea->setCursorPositionInDocument(pos, true);
_textArea->ensureVisibleCursor();
}
void Lister::saveAs()
{
const QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister"));
if (url.isEmpty())
return;
QUrl sourceUrl;
if (!_downloading)
sourceUrl = QUrl::fromLocalFile(_filePath);
else
sourceUrl = this->url();
QList urlList;
urlList << sourceUrl;
KIO::Job *job = KIO::copy(urlList, url);
job->setUiDelegate(new KIO::JobUiDelegate());
KIO::getJobTracker()->registerJob(job);
job->uiDelegate()->setAutoErrorHandlingEnabled(true);
}
void Lister::saveSelected()
{
bool isfirst;
const qint64 start = _textArea->getCursorAnchor();
const qint64 end = _textArea->getCursorPosition(isfirst);
if (start == -1 || start == end) {
KMessageBox::error(_textArea, i18n("Nothing is selected."), i18n("Save selection..."));
return;
}
if (start > end) {
_savePosition = end;
_saveEnd = start;
} else {
_savePosition = start;
_saveEnd = end;
}
const QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister"));
if (url.isEmpty())
return;
- KIO::Job *saveJob = KIO::put(url, -1, KIO::Overwrite);
- connect(saveJob, SIGNAL(dataReq(KIO::Job*,QByteArray&)),
- this, SLOT(slotDataSend(KIO::Job*,QByteArray&)));
- connect(saveJob, SIGNAL(result(KJob*)),
- this, SLOT(slotSendFinished(KJob*)));
+ KIO::TransferJob *saveJob = KIO::put(url, -1, KIO::Overwrite);
+ connect(saveJob, &KIO::TransferJob::dataReq, this, &Lister::slotDataSend);
+ connect(saveJob, &KIO::TransferJob::result, this, &Lister::slotSendFinished);
saveJob->setUiDelegate(new KIO::JobUiDelegate());
KIO::getJobTracker()->registerJob(saveJob);
saveJob->uiDelegate()->setAutoErrorHandlingEnabled(true);
_actionSaveSelected->setEnabled(false);
}
void Lister::slotDataSend(KIO::Job *, QByteArray &array)
{
if (_savePosition >= _saveEnd) {
array = QByteArray();
return;
}
qint64 max = _saveEnd - _savePosition;
if (max > 1000)
max = 1000;
array = cacheChunk(_savePosition, (int) max);
_savePosition += array.size();
}
void Lister::slotSendFinished(KJob *)
{
_actionSaveSelected->setEnabled(true);
}
void Lister::setCharacterSet(const QString set)
{
_characterSet = set;
if (_characterSet.isEmpty()) {
_codec = QTextCodec::codecForLocale();
} else {
_codec = KCharsets::charsets()->codecForName(_characterSet);
}
_textArea->redrawTextArea(true);
}
void Lister::print()
{
bool isfirst;
const qint64 anchor = _textArea->getCursorAnchor();
const qint64 cursor = _textArea->getCursorPosition(isfirst);
const bool hasSelection = (anchor != -1 && anchor != cursor);
const QString docName = url().fileName();
QPrinter printer;
printer.setDocName(docName);
QScopedPointer printDialog(new QPrintDialog(&printer, _textArea));
if (hasSelection) {
printDialog->addEnabledOption(QAbstractPrintDialog::PrintSelection);
}
if (!printDialog->exec()) {
return;
}
if (printer.pageOrder() == QPrinter::LastPageFirst) {
switch (KMessageBox::warningContinueCancel(_textArea,
i18n("Reverse printing is not supported. Continue with normal printing?"))) {
case KMessageBox::Continue :
break;
default:
return;
}
}
QPainter painter;
painter.begin(&printer);
const QString dateString = QDate::currentDate().toString(Qt::SystemLocaleShortDate);
const QRect pageRect = printer.pageRect();
const QRect drawingRect(0, 0, pageRect.width(), pageRect.height());
const QFont normalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
const QFontMetrics fmNormal(normalFont);
const int normalFontHeight = fmNormal.height();
const QFontMetrics fmFixed(fixedFont);
const int fixedFontHeight = std::max(fmFixed.height(), 1);
const int fixedFontWidth = std::max(fmFixed.width("W"), 1);
const int effPageSize = drawingRect.height() - normalFontHeight - 1;
const int rowsPerPage = std::max(effPageSize / fixedFontHeight, 1);
const int columnsPerPage = std::max(drawingRect.width() / fixedFontWidth, 1);
bool firstPage = true;
qint64 startPos = 0;
qint64 endPos = _fileSize;
if (printer.printRange() == QPrinter::Selection) {
if (anchor > cursor)
startPos = cursor, endPos = anchor;
else
startPos = anchor, endPos = cursor;
}
int page = 0;
while (startPos < endPos) {
page++;
QStringList rows = readLines(startPos, endPos, columnsPerPage, rowsPerPage);
// print since set-up fromPage number
if (printer.fromPage() && page < printer.fromPage()) {
continue;
}
// print until set-up toPage number
if (printer.toPage() && printer.toPage() >= printer.fromPage() && page > printer.toPage())
break;
if (!firstPage) {
printer.newPage();
}
firstPage = false;
// Use the painter to draw on the page.
painter.setFont(normalFont);
painter.drawText(drawingRect, Qt::AlignLeft, dateString);
painter.drawText(drawingRect, Qt::AlignHCenter, docName);
painter.drawText(drawingRect, Qt::AlignRight, QString("%1").arg(page));
painter.drawLine(0, normalFontHeight, drawingRect.width(), normalFontHeight);
painter.setFont(fixedFont);
int yOffset = normalFontHeight + 1;
foreach (const QString &row, rows) {
painter.drawText(0, yOffset + fixedFontHeight, row);
yOffset += fixedFontHeight;
}
}
}
QStringList Lister::readLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines)
{
if (_textArea->hexMode()) {
return readHexLines(filePos, endPos, columns, lines);
}
QStringList list;
const int maxBytes = std::min(columns * lines * MAX_CHAR_LENGTH, (int) (endPos - filePos));
if (maxBytes <= 0) {
return list;
}
const QByteArray chunk = cacheChunk(filePos, maxBytes);
if (chunk.isEmpty()) {
return list;
}
QScopedPointer decoder(_codec->makeDecoder());
int byteCounter = 0;
QString row = "";
bool skipImmediateNewline = false;
while (byteCounter < chunk.size() && list.size() < lines) {
QString chr = decoder->toUnicode(chunk.mid(byteCounter++, 1));
if (chr.isEmpty()) {
continue;
}
// replace unreadable characters
if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) {
chr = QChar(' ');
}
// handle newline
if (chr == "\n") {
if (!skipImmediateNewline) {
list << row;
row = "";
}
skipImmediateNewline = false;
continue;
}
skipImmediateNewline = false;
// handle tab
if (chr == "\t") {
const int tabLength = _textArea->tabWidth() - (row.length() % _textArea->tabWidth());
if (row.length() + tabLength > columns) {
list << row;
row = "";
}
row += QString(tabLength, QChar(' '));
} else {
// normal printable character
row += chr;
}
if (row.length() >= columns) {
list << row;
row = "";
skipImmediateNewline = true;
}
}
if (list.size() < lines) {
list << row;
}
filePos += byteCounter;
return list;
}
int Lister::hexPositionDigits()
{
int positionDigits = 0;
qint64 checker = _fileSize;
while (checker) {
positionDigits++;
checker /= 16;
}
if (positionDigits < 8) {
return 8;
}
return positionDigits;
}
int Lister::hexBytesPerLine(const int columns)
{
const int positionDigits = hexPositionDigits();
if (columns >= positionDigits + 5 + 128) {
return 32;
}
if (columns >= positionDigits + 5 + 64) {
return 16;
}
return 8;
}
QStringList Lister::readHexLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines)
{
const int positionDigits = hexPositionDigits();
const int bytesPerRow = hexBytesPerLine(columns);
QStringList list;
const qint64 choppedPos = (filePos / bytesPerRow) * bytesPerRow;
const int maxBytes = std::min(bytesPerRow * lines, (int) (endPos - choppedPos));
if (maxBytes <= 0)
return list;
const QByteArray chunk = cacheChunk(choppedPos, maxBytes);
if (chunk.isEmpty())
return list;
int cnt = 0;
for (int l = 0; l < lines; l++) {
if (filePos >= endPos) {
break;
}
const qint64 printPos = (filePos / bytesPerRow) * bytesPerRow;
QString pos;
pos.setNum(printPos, 16);
while (pos.length() < positionDigits)
pos = QString("0") + pos;
pos = QString("0x") + pos;
pos += QString(": ");
QString charData;
for (int i = 0; i != bytesPerRow; ++i, ++cnt) {
const qint64 currentPos = printPos + i;
if (currentPos < filePos || currentPos >= endPos) {
pos += QString(" ");
charData += QString(" ");
} else {
char c = chunk.at(cnt);
int charCode = (int)c;
if (charCode < 0)
charCode += 256;
QString hex;
hex.setNum(charCode, 16);
if (hex.length() < 2)
hex = QString("0") + hex;
pos += hex + QString(" ");
if (c < 32)
c = '.';
charData += QChar(c);
}
}
pos += QString(" ") + charData;
list << pos;
filePos = printPos + bytesPerRow;
}
if (filePos > endPos) {
filePos = endPos;
}
return list;
}
int Lister::hexIndexToPosition(const int columns, const int index)
{
const int positionDigits = hexPositionDigits();
const int bytesPerRow = hexBytesPerLine(columns);
const int finalIndex = std::min(index, bytesPerRow);
return positionDigits + 4 + (3*finalIndex);
}
int Lister::hexPositionToIndex(const int columns, const int position)
{
const int positionDigits = hexPositionDigits();
const int bytesPerRow = hexBytesPerLine(columns);
int finalPosition = position;
finalPosition -= 4 + positionDigits;
if (finalPosition <= 0)
return 0;
finalPosition /= 3;
if (finalPosition >= bytesPerRow)
return bytesPerRow;
return finalPosition;
}
void Lister::toggleHexMode()
{
setHexMode(!_textArea->hexMode());
}
void Lister::setHexMode(const bool mode)
{
if (mode) {
_textArea->setHexMode(true);
_actionHexMode->setText(i18n("Text mode"));
} else {
_textArea->setHexMode(false);
_actionHexMode->setText(i18n("Hex mode"));
}
}
diff --git a/krusader/KViewer/lister.h b/krusader/KViewer/lister.h
index f0564bc9..baca7989 100644
--- a/krusader/KViewer/lister.h
+++ b/krusader/KViewer/lister.h
@@ -1,318 +1,320 @@
/*****************************************************************************
* Copyright (C) 2009 Csaba Karai *
* Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#ifndef LISTER_H
#define LISTER_H
// QtCore
#include
#include
#include
#include
// QtGui
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include "../FileSystem/krquery.h"
#define SLIDER_MAX 10000
#define MAX_CHAR_LENGTH 4
class Lister;
class QLabel;
class QProgressBar;
class QPushButton;
class QToolButton;
class QAction;
class QTemporaryFile;
class ListerEncodingMenu;
class ListerTextArea : public KTextEdit
{
Q_OBJECT
public:
ListerTextArea(Lister *lister, QWidget *parent);
void reset();
void calculateText(const bool forcedUpdate = false);
void redrawTextArea(const bool forcedUpdate = false);
qint64 textToFilePositionOnScreen(const int x, const int y, bool &isfirst);
void fileToTextPositionOnScreen(const qint64 p, const bool isfirst, int &x, int &y);
int tabWidth() {
return _tabWidth;
}
bool hexMode() {
return _hexMode;
}
void setHexMode(const bool hexMode);
void copySelectedToClipboard();
QString getSelectedText();
void clearSelection();
void getCursorPosition(int &x, int &y);
qint64 getCursorPosition(bool &isfirst);
qint64 getCursorAnchor() {
return _cursorAnchorPos;
}
void setCursorPositionInDocument(const qint64 p, const bool isfirst);
void ensureVisibleCursor();
void deleteAnchor() {
_cursorAnchorPos = -1;
}
void setAnchorAndCursor(const qint64 anchor, const qint64 cursor);
void sizeChanged();
protected:
virtual void resizeEvent(QResizeEvent * event) Q_DECL_OVERRIDE;
virtual void keyPressEvent(QKeyEvent * e) Q_DECL_OVERRIDE;
virtual void mousePressEvent(QMouseEvent * e) Q_DECL_OVERRIDE;
virtual void mouseDoubleClickEvent(QMouseEvent * e) Q_DECL_OVERRIDE;
virtual void mouseMoveEvent(QMouseEvent * e) Q_DECL_OVERRIDE;
virtual void wheelEvent(QWheelEvent * event) Q_DECL_OVERRIDE;
QStringList readLines(const qint64 filePos, qint64 &endPos, const int lines, QList * locs = 0);
QString readSection(qint64 p1, qint64 p2);
void setUpScrollBar();
void setCursorPositionOnScreen(const int x, const int y, const int anchorX = -1, const int anchorY = -1);
void handleAnchorChange(const int oldAnchor);
void performAnchorChange(const int anchor);
void getScreenPosition(const int position, int &x, int &y);
-protected slots:
+public slots:
void slotActionTriggered(const int action);
+
+protected slots:
void slotCursorPositionChanged();
void zoomIn(const int range = 1);
void zoomOut(const int range = 1);
protected:
Lister *_lister;
qint64 _screenStartPos = 0;
qint64 _screenEndPos = 0;
qint64 _averagePageSize = 0;
qint64 _lastPageStartPos = 0;
int _sizeX = -1;
int _sizeY = -1;
int _pageSize = 0;
int _tabWidth = 4;
bool _sizeChanged = false;
QStringList _rowContent;
QList _rowStarts;
qint64 _cursorPos = -1;
bool _cursorAtFirstColumn = true;
bool _skipCursorChangedListener = false;
qint64 _cursorAnchorPos = -1;
int _skippedLines = 0;
bool _inSliderOp = false;
bool _hexMode = false;
bool _redrawing = false;
QMutex _cursorBlinkMutex;
QTimer _blinkTimer;
};
class ListerBrowserExtension : public KParts::BrowserExtension
{
Q_OBJECT
public:
explicit ListerBrowserExtension(Lister * lister);
public slots:
void copy();
void print();
protected:
Lister *_lister;
};
class ListerPane : public QWidget
{
Q_OBJECT
public:
ListerPane(Lister *lister, QWidget *parent);
protected:
virtual bool event(QEvent *event) Q_DECL_OVERRIDE;
protected:
bool handleCloseEvent(QEvent *e);
Lister *_lister;
};
class Lister : public KParts::ReadOnlyPart
{
Q_OBJECT
public:
explicit Lister(QWidget *parent);
QScrollBar *scrollBar() {
return _scrollBar;
}
ListerTextArea *textArea() {
return _textArea;
}
inline qint64 fileSize() {
return _fileSize;
}
QByteArray cacheChunk(const qint64 filePos, const int maxSize);
bool isSearchEnabled();
void enableSearch(const bool);
void enableActions(const bool);
QString characterSet() { return _characterSet; }
QTextCodec *codec() { return _codec; }
void setCharacterSet(const QString set);
void setHexMode(const bool);
QStringList readHexLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines);
int hexBytesPerLine(const int columns);
int hexPositionDigits();
int hexIndexToPosition(const int columns, const int index);
int hexPositionToIndex(const int columns, const int position);
public slots:
void searchAction() {
enableSearch(true);
}
void searchNext();
void searchPrev();
void searchDelete();
void jumpToPosition();
void saveAs();
void saveSelected();
void print();
void toggleHexMode();
void slotUpdate();
protected slots:
void slotSearchMore();
void searchSucceeded();
void searchFailed();
void searchTextChanged();
void slotDataSend(KIO::Job *, QByteArray &);
void slotSendFinished(KJob *);
protected:
virtual bool openUrl(const QUrl &url) Q_DECL_OVERRIDE;
virtual bool closeUrl() Q_DECL_OVERRIDE {
return true;
}
virtual bool openFile() Q_DECL_OVERRIDE {
return true;
}
virtual void guiActivateEvent(KParts::GUIActivateEvent * event) Q_DECL_OVERRIDE;
void setColor(const bool match, const bool restore);
void hideProgressBar();
void updateProgressBar();
void resetSearchPosition();
qint64 getFileSize();
void search(const bool forward, const bool restart = false);
QStringList readLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines);
QTimer _searchUpdateTimer;
ListerTextArea *_textArea;
QScrollBar *_scrollBar;
QLabel *_listerLabel;
KLineEdit *_searchLineEdit;
QProgressBar *_searchProgressBar;
QToolButton *_searchStopButton;
QPushButton *_searchNextButton;
QPushButton *_searchPrevButton;
bool _searchInProgress = false;
bool _searchHexadecimal = false;
QPushButton *_searchOptions;
QLabel *_statusLabel;
QAction *_fromCursorAction;
QAction *_caseSensitiveAction;
QAction *_matchWholeWordsOnlyAction;
QAction *_regExpAction;
QAction *_hexAction;
QAction *_actionSaveSelected;
QAction *_actionSaveAs;
QAction *_actionPrint;
QAction *_actionSearch;
QAction *_actionSearchNext;
QAction *_actionSearchPrev;
QAction *_actionJumpToPosition;
QAction *_actionHexMode;
QString _filePath;
qint64 _fileSize = 0;
QByteArray _cache;
qint64 _cachePos = 0;
KRQuery _searchQuery;
QByteArray _searchHexQuery;
qint64 _searchPosition = 0;
bool _searchIsForward = true;
qint64 _searchLastFailedPosition = -1;
int _searchProgressCounter = 0;
QColor _originalBackground;
QColor _originalForeground;
QString _characterSet;
QTextCodec *_codec = QTextCodec::codecForLocale();
QTemporaryFile *_tempFile = 0;
bool _downloading = false;
bool _restartFromBeginning = false;
QTimer _downloadUpdateTimer;
qint64 _savePosition = 0;
qint64 _saveEnd = 0;
};
#endif // __LISTER_H__
diff --git a/krusader/KViewer/panelviewer.cpp b/krusader/KViewer/panelviewer.cpp
index 9f8766cd..57c1834d 100644
--- a/krusader/KViewer/panelviewer.cpp
+++ b/krusader/KViewer/panelviewer.cpp
@@ -1,424 +1,424 @@
/*****************************************************************************
* Copyright (C) 2002 Shie Erlich *
* Copyright (C) 2002 Rafi Yanai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "panelviewer.h"
// QtCore
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "lister.h"
#include "../defaults.h"
#define DICTSIZE 211
PanelViewerBase::PanelViewerBase(QWidget *parent, KrViewer::Mode mode) :
QStackedWidget(parent), mimes(0), cpart(0), mode(mode)
{
setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored));
mimes = new QHash >();
cpart = 0;
// NOTE: the fallback should be never visible. The viewer is not opened without a file and the
// tab is closed if a file cannot be opened.
fallback = new QLabel(i18n("No file selected or selected file cannot be displayed."), this);
fallback->setAlignment(Qt::Alignment(QFlag(Qt::AlignCenter | Qt::TextExpandTabs)));
fallback->setWordWrap(true);
addWidget(fallback);
setCurrentWidget(fallback);
}
PanelViewerBase::~PanelViewerBase()
{
// cpart->queryClose();
closeUrl();
QHashIterator< QString, QPointer > lit(*mimes);
while (lit.hasNext()) {
QPointer p = lit.next().value();
if (p)
delete p;
}
mimes->clear();
delete mimes;
delete fallback;
}
void PanelViewerBase::slotStatResult(KJob* job)
{
if (job->error()) {
KMessageBox::error(this, job->errorString());
emit openUrlFinished(this, false);
} else {
KIO::UDSEntry entry = static_cast(job)->statResult();
openFile(KFileItem(entry, curl));
}
}
KParts::ReadOnlyPart* PanelViewerBase::getPart(QString mimetype)
{
KParts::ReadOnlyPart* part = 0;
if (mimes->find(mimetype) == mimes->end()) {
part = createPart(mimetype);
if(part)
mimes->insert(mimetype, part);
} else
part = (*mimes)[mimetype];
return part;
}
void PanelViewerBase::openUrl(QUrl url)
{
closeUrl();
curl = url;
emit urlChanged(this, url);
if (url.isLocalFile())
openFile(KFileItem(url));
else {
KIO::StatJob* statJob = KIO::stat(url, KIO::HideProgressInfo);
- connect(statJob, SIGNAL(result(KJob*)), this, SLOT(slotStatResult(KJob*)));
+ connect(statJob, &KIO::StatJob::result, this, &PanelViewerBase::slotStatResult);
}
}
/* ----==={ PanelViewer }===---- */
PanelViewer::PanelViewer(QWidget *parent, KrViewer::Mode mode) :
PanelViewerBase(parent, mode)
{
}
PanelViewer::~PanelViewer()
{
}
KParts::ReadOnlyPart* PanelViewer::getListerPart(bool hexMode)
{
KParts::ReadOnlyPart* part = 0;
if (mimes->find(QLatin1String("krusader_lister")) == mimes->end()) {
part = new Lister(this);
mimes->insert(QLatin1String("krusader_lister"), part);
} else
part = (*mimes)[ QLatin1String("krusader_lister")];
if (part) {
Lister *lister = dynamic_cast((KParts::ReadOnlyPart *)part);
if (lister)
lister->setHexMode(hexMode);
}
return part;
}
KParts::ReadOnlyPart* PanelViewer::getHexPart()
{
KParts::ReadOnlyPart* part = 0;
if (KConfigGroup(krConfig, "General").readEntry("UseOktetaViewer", _UseOktetaViewer)) {
if (mimes->find("oktetapart") == mimes->end()) {
KPluginLoader loader("oktetapart");
if (KPluginFactory *factory = loader.factory()) {
if ((part = factory->create(this, this)))
mimes->insert("oktetapart", part);
}
} else
part = (*mimes)["oktetapart"];
}
return part ? part : getListerPart(true);
}
KParts::ReadOnlyPart* PanelViewer::getTextPart()
{
KParts::ReadOnlyPart* part = getPart("text/plain");
if(!part)
part = getPart("all/allfiles");
return part ? part : getListerPart();
}
KParts::ReadOnlyPart* PanelViewer::getDefaultPart(KFileItem fi)
{
KConfigGroup group(krConfig, "General");
QString modeString = group.readEntry("Default Viewer Mode", QString("generic"));
KrViewer::Mode mode = KrViewer::Generic;
if (modeString == "generic") mode = KrViewer::Generic;
else if (modeString == "text") mode = KrViewer::Text;
else if (modeString == "hex") mode = KrViewer::Hex;
else if (modeString == "lister") mode = KrViewer::Lister;
QMimeType mimeType = fi.determineMimeType();
bool isBinary = false;
if (mode == KrViewer::Generic || mode == KrViewer::Lister) {
isBinary = !mimeType.inherits(QStringLiteral("text/plain"));
}
KIO::filesize_t fileSize = fi.size();
KIO::filesize_t limit = (KIO::filesize_t)group.readEntry("Lister Limit", _ListerLimit) * 0x100000;
QString mimetype = fi.mimetype();
KParts::ReadOnlyPart* part = 0;
switch(mode) {
case KrViewer::Generic:
if ((mimetype.startsWith(QLatin1String("text/")) ||
mimetype.startsWith(QLatin1String("all/"))) &&
fileSize > limit) {
part = getListerPart(isBinary);
break;
} else if ((part = getPart(mimetype))) {
break;
}
#if __GNUC__ >= 7
[[gnu::fallthrough]];
#endif
case KrViewer::Text:
part = fileSize > limit ? getListerPart(false) : getTextPart();
break;
case KrViewer::Lister:
part = getListerPart(isBinary);
break;
case KrViewer::Hex:
part = fileSize > limit ? getListerPart(true) : getHexPart();
break;
default:
abort();
}
return part;
}
void PanelViewer::openFile(KFileItem fi)
{
switch(mode) {
case KrViewer::Generic:
cpart = getPart(fi.mimetype());
break;
case KrViewer::Text:
cpart = getTextPart();
break;
case KrViewer::Lister:
cpart = getListerPart();
break;
case KrViewer::Hex:
cpart = getHexPart();
break;
case KrViewer::Default:
cpart = getDefaultPart(fi);
break;
default:
abort();
}
if(cpart) {
addWidget(cpart->widget());
setCurrentWidget(cpart->widget());
if (cpart->inherits("KParts::ReadWritePart"))
static_cast(cpart.data())->setReadWrite(false);
KParts::OpenUrlArguments args;
args.setReload(true);
cpart->setArguments(args);
if (cpart->openUrl(curl)) {
- connect(cpart, SIGNAL(destroyed()), this, SLOT(slotCPartDestroyed()));
+ connect(cpart.data(), &KParts::ReadOnlyPart::destroyed, this, &PanelViewer::slotCPartDestroyed);
emit openUrlFinished(this, true);
return;
}
}
setCurrentWidget(fallback);
emit openUrlFinished(this, false);
}
bool PanelViewer::closeUrl()
{
setCurrentWidget(fallback);
if (cpart && cpart->closeUrl()) {
cpart = 0;
return true;
}
return false;
}
KParts::ReadOnlyPart* PanelViewer::createPart(QString mimetype)
{
KParts::ReadOnlyPart * part = 0;
KService::Ptr ptr = KMimeTypeTrader::self()->preferredService(mimetype, "KParts/ReadOnlyPart");
if (ptr) {
QVariantList args;
QVariant argsProp = ptr->property("X-KDE-BrowserView-Args");
if (argsProp.isValid())
args << argsProp;
QVariant prop = ptr->property("X-KDE-BrowserView-AllowAsDefault");
if (!prop.isValid() || prop.toBool()) // defaults to true
part = ptr->createInstance(this, this, args);
}
if (part) {
KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject(part);
if (ext) {
- connect(ext, SIGNAL(openUrlRequestDelayed(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)), this, SLOT(openUrl(QUrl)));
- connect(ext, SIGNAL(openUrlRequestDelayed(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)), this, SIGNAL(openUrlRequest(QUrl)));
+ connect(ext, &KParts::BrowserExtension::openUrlRequestDelayed, this, &PanelViewer::openUrl);
+ connect(ext, &KParts::BrowserExtension::openUrlRequestDelayed, this, &PanelViewer::openUrlRequest);
}
}
return part;
}
/* ----==={ PanelEditor }===---- */
PanelEditor::PanelEditor(QWidget *parent, KrViewer::Mode mode) :
PanelViewerBase(parent, mode)
{
}
PanelEditor::~PanelEditor()
{
}
void PanelEditor::configureDeps()
{
KService::Ptr ptr = KMimeTypeTrader::self()->preferredService("text/plain", "KParts/ReadWritePart");
if (!ptr)
ptr = KMimeTypeTrader::self()->preferredService("all/allfiles", "KParts/ReadWritePart");
if (!ptr)
KMessageBox::sorry(0, missingKPartMsg(), i18n("Missing Plugin"), KMessageBox::AllowLink);
}
QString PanelEditor::missingKPartMsg()
{
return i18nc("missing kpart - arg1 is a URL",
"No text editor plugin available.
"
"Internal editor will not work without this.
"
"You can fix this by installing Kate:
%1",
QString("%1").arg(
"http://www.kde.org/applications/utilities/kate"));
}
void PanelEditor::openFile(KFileItem fi)
{
KIO::filesize_t fileSize = fi.size();
KConfigGroup group(krConfig, "General");
KIO::filesize_t limitMB = (KIO::filesize_t)group.readEntry("Lister Limit", _ListerLimit);
QString mimetype = fi.mimetype();
if (mode == KrViewer::Generic)
cpart = getPart(mimetype);
if(fileSize > limitMB * 0x100000) {
if(!cpart || mimetype.startsWith(QLatin1String("text/")) ||
mimetype.startsWith(QLatin1String("all/"))) {
if(KMessageBox::Cancel == KMessageBox::warningContinueCancel(this,
i18n("%1 is bigger than %2 MB" , curl.toDisplayString(QUrl::PreferLocalFile), limitMB))) {
setCurrentWidget(fallback);
emit openUrlFinished(this, false);
return;
}
}
}
if (!cpart)
cpart = getPart("text/plain");
if (!cpart)
cpart = getPart("all/allfiles");
if (cpart) {
addWidget(cpart->widget());
setCurrentWidget(cpart->widget());
KParts::OpenUrlArguments args;
args.setReload(true);
cpart->setArguments(args);
if (cpart->openUrl(curl)) {
- connect(cpart, SIGNAL(destroyed()), this, SLOT(slotCPartDestroyed()));
+ connect(cpart.data(), &KParts::ReadOnlyPart::destroyed, this, &PanelEditor::slotCPartDestroyed);
emit openUrlFinished(this, true);
return;
} // else: don't show error message - assume this has been done by the editor part
} else
KMessageBox::sorry(this, missingKPartMsg(), i18n("Cannot edit %1", curl.toDisplayString(QUrl::PreferLocalFile)),
KMessageBox::AllowLink);
setCurrentWidget(fallback);
emit openUrlFinished(this, false);
}
bool PanelEditor::queryClose()
{
if (!cpart) return true;
return static_cast((KParts::ReadOnlyPart *)cpart)->queryClose();
}
bool PanelEditor::closeUrl()
{
if (!cpart) return false;
static_cast((KParts::ReadOnlyPart *)cpart)->closeUrl(false);
setCurrentWidget(fallback);
cpart = 0;
return true;
}
KParts::ReadOnlyPart* PanelEditor::createPart(QString mimetype)
{
KParts::ReadWritePart * part = 0L;
KService::Ptr ptr = KMimeTypeTrader::self()->preferredService(mimetype, "KParts/ReadWritePart");
if (ptr) {
QVariantList args;
QVariant argsProp = ptr->property("X-KDE-BrowserView-Args");
if (argsProp.isValid())
args << argsProp;
QVariant prop = ptr->property("X-KDE-BrowserView-AllowAsDefault");
if (!prop.isValid() || prop.toBool()) // defaults to true
part = ptr->createInstance(this, this, args);
}
if (part) {
KParts::BrowserExtension * ext = KParts::BrowserExtension::childObject(part);
if (ext) {
- connect(ext, SIGNAL(openUrlRequestDelayed(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)), this, SLOT(openUrl(QUrl)));
- connect(ext, SIGNAL(openUrlRequestDelayed(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)), this, SIGNAL(openUrlRequest(QUrl)));
+ connect(ext, &KParts::BrowserExtension::openUrlRequestDelayed, this, &PanelEditor::openUrl);
+ connect(ext, &KParts::BrowserExtension::openUrlRequestDelayed, this, &PanelEditor::openUrlRequest);
}
}
return part;
}
bool PanelEditor::isModified()
{
if (cpart)
return static_cast((KParts::ReadOnlyPart *)cpart)->isModified();
else
return false;
}
diff --git a/krusader/Konfigurator/konfiguratoritems.cpp b/krusader/Konfigurator/konfiguratoritems.cpp
index 71d994e1..78b8f1ab 100644
--- a/krusader/Konfigurator/konfiguratoritems.cpp
+++ b/krusader/Konfigurator/konfiguratoritems.cpp
@@ -1,836 +1,836 @@
/*****************************************************************************
* Copyright (C) 2003 Csaba Karai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "konfiguratoritems.h"
#include "../krglobal.h"
#include "../icon.h"
// QtCore
#include
// QtGui
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
KonfiguratorExtension::KonfiguratorExtension(QObject *obj, QString cfgGroup, QString cfgName,
bool restartNeeded, int page)
: QObject(), objectPtr(obj), applyConnected(false), setDefaultsConnected(false), changed(false),
restartNeeded(restartNeeded), subpage(page), configGroup(cfgGroup), configName(cfgName)
{
}
void KonfiguratorExtension::connectNotify(const QMetaMethod &signal)
{
if (signal == QMetaMethod::fromSignal(&KonfiguratorExtension::applyManually))
applyConnected = true;
else if (signal == QMetaMethod::fromSignal(&KonfiguratorExtension::setDefaultsManually))
setDefaultsConnected = true;
QObject::connectNotify(signal);
}
bool KonfiguratorExtension::apply()
{
if (!changed)
return false;
if (applyConnected)
emit applyManually(objectPtr, configGroup, configName);
else
emit applyAuto(objectPtr, configGroup, configName);
setChanged(false);
return restartNeeded;
}
void KonfiguratorExtension::setDefaults()
{
if (setDefaultsConnected)
emit setDefaultsManually(objectPtr);
else
emit setDefaultsAuto(objectPtr);
}
void KonfiguratorExtension::loadInitialValue()
{
emit setInitialValue(objectPtr);
}
bool KonfiguratorExtension::isChanged()
{
return changed;
}
// KonfiguratorCheckBox class
///////////////////////////////
KonfiguratorCheckBox::KonfiguratorCheckBox(QString configGroup, QString name, bool defaultValue, QString text,
QWidget *parent, bool restart, int page) : QCheckBox(text, parent),
defaultValue(defaultValue)
{
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorCheckBox::slotApply);
connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorCheckBox::slotSetDefaults);
connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorCheckBox::loadInitialValue);
connect(this, &KonfiguratorCheckBox::stateChanged, ext, QOverload<>::of(&KonfiguratorExtension::setChanged));
loadInitialValue();
}
KonfiguratorCheckBox::~KonfiguratorCheckBox()
{
delete ext;
}
void KonfiguratorCheckBox::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
setChecked(group.readEntry(ext->getConfigName(), defaultValue));
ext->setChanged(false);
}
void KonfiguratorCheckBox::checkStateSet()
{
QCheckBox::checkStateSet();
updateDeps();
}
void KonfiguratorCheckBox::nextCheckState()
{
QCheckBox::nextCheckState();
updateDeps();
}
void KonfiguratorCheckBox::addDep(KonfiguratorCheckBox *dep)
{
deps << dep;
dep->setEnabled(isChecked());
}
void KonfiguratorCheckBox::updateDeps()
{
foreach(KonfiguratorCheckBox *dep, deps)
dep->setEnabled(isChecked());
}
void KonfiguratorCheckBox::slotApply(QObject *, QString configGroup, QString name)
{
KConfigGroup(krConfig, configGroup).writeEntry(name, isChecked());
}
void KonfiguratorCheckBox::slotSetDefaults(QObject *)
{
if (isChecked() != defaultValue)
setChecked(defaultValue);
}
// KonfiguratorSpinBox class
///////////////////////////////
KonfiguratorSpinBox::KonfiguratorSpinBox(QString configGroup, QString configName, int defaultValue,
int min, int max, QWidget *parent, bool restartNeeded,
int page)
: QSpinBox(parent), defaultValue(defaultValue)
{
ext = new KonfiguratorExtension(this, configGroup, configName, restartNeeded, page);
connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorSpinBox::slotApply);
connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorSpinBox::slotSetDefaults);
connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorSpinBox::loadInitialValue);
connect(this, QOverload::of(&KonfiguratorSpinBox::valueChanged), ext, QOverload<>::of(&KonfiguratorExtension::setChanged));
setMinimum(min);
setMaximum(max);
loadInitialValue();
}
KonfiguratorSpinBox::~KonfiguratorSpinBox()
{
delete ext;
}
void KonfiguratorSpinBox::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
setValue(group.readEntry(ext->getConfigName(), defaultValue));
ext->setChanged(false);
}
void KonfiguratorSpinBox::slotApply(QObject *, QString configGroup, QString name)
{
KConfigGroup(krConfig, configGroup).writeEntry(name, value());
}
void KonfiguratorSpinBox::slotSetDefaults(QObject *)
{
if (value() != defaultValue)
setValue(defaultValue);
}
// KonfiguratorCheckBoxGroup class
///////////////////////////////
void KonfiguratorCheckBoxGroup::add(KonfiguratorCheckBox *checkBox)
{
checkBoxList.append(checkBox);
}
KonfiguratorCheckBox * KonfiguratorCheckBoxGroup::find(int index)
{
if (index < 0 || index >= checkBoxList.count())
return 0;
return checkBoxList.at(index);
}
KonfiguratorCheckBox * KonfiguratorCheckBoxGroup::find(QString name)
{
QListIterator it(checkBoxList);
while (it.hasNext()) {
KonfiguratorCheckBox * checkBox = it.next();
if (checkBox->extension()->getConfigName() == name)
return checkBox;
}
return 0;
}
// KonfiguratorRadioButtons class
///////////////////////////////
KonfiguratorRadioButtons::KonfiguratorRadioButtons(QString configGroup, QString name,
QString defaultValue, QWidget *parent, bool restart, int page) :
QWidget(parent), defaultValue(defaultValue)
{
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorRadioButtons::slotApply);
connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorRadioButtons::slotSetDefaults);
connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorRadioButtons::loadInitialValue);
}
KonfiguratorRadioButtons::~KonfiguratorRadioButtons()
{
delete ext;
}
void KonfiguratorRadioButtons::addRadioButton(QRadioButton *radioWidget, QString name, QString value)
{
radioButtons.append(radioWidget);
radioNames.push_back(name);
radioValues.push_back(value);
connect(radioWidget, &QRadioButton::toggled, ext, QOverload<>::of(&KonfiguratorExtension::setChanged));
}
QRadioButton * KonfiguratorRadioButtons::find(int index)
{
if (index < 0 || index >= radioButtons.count())
return 0;
return radioButtons.at(index);
}
QRadioButton * KonfiguratorRadioButtons::find(QString name)
{
int index = radioNames.indexOf(name);
if (index == -1)
return 0;
return radioButtons.at(index);
}
void KonfiguratorRadioButtons::selectButton(QString value)
{
int cnt = 0;
QListIterator it(radioButtons);
while (it.hasNext()) {
QRadioButton * btn = it.next();
if (value == radioValues[ cnt ]) {
btn->setChecked(true);
return;
}
cnt++;
}
if (!radioButtons.isEmpty())
radioButtons.first()->setChecked(true);
}
void KonfiguratorRadioButtons::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
QString initValue = group.readEntry(ext->getConfigName(), defaultValue);
selectButton(initValue);
ext->setChanged(false);
}
QString KonfiguratorRadioButtons::selectedValue()
{
int cnt = 0;
QListIterator it(radioButtons);
while (it.hasNext()) {
QRadioButton * btn = it.next();
if (btn->isChecked()) {
return radioValues[ cnt ];
}
cnt++;
}
return QString();
}
void KonfiguratorRadioButtons::slotApply(QObject *, QString configGroup, QString name)
{
QString value = selectedValue();
if (!value.isEmpty())
KConfigGroup(krConfig, configGroup).writeEntry(name, value);
}
void KonfiguratorRadioButtons::slotSetDefaults(QObject *)
{
selectButton(defaultValue);
}
// KonfiguratorEditBox class
///////////////////////////////
KonfiguratorEditBox::KonfiguratorEditBox(QString configGroup, QString name, QString defaultValue,
QWidget *parent, bool restart, int page) : QLineEdit(parent),
defaultValue(defaultValue)
{
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorEditBox::slotApply);
connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorEditBox::slotSetDefaults);
connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorEditBox::loadInitialValue);
connect(this, &KonfiguratorEditBox::textChanged, ext, QOverload<>::of(&KonfiguratorExtension::setChanged));
loadInitialValue();
}
KonfiguratorEditBox::~KonfiguratorEditBox()
{
delete ext;
}
void KonfiguratorEditBox::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
setText(group.readEntry(ext->getConfigName(), defaultValue));
ext->setChanged(false);
}
void KonfiguratorEditBox::slotApply(QObject *, QString configGroup, QString name)
{
KConfigGroup(krConfig, configGroup).writeEntry(name, text());
}
void KonfiguratorEditBox::slotSetDefaults(QObject *)
{
if (text() != defaultValue)
setText(defaultValue);
}
// KonfiguratorURLRequester class
///////////////////////////////
KonfiguratorURLRequester::KonfiguratorURLRequester(QString configGroup, QString name,
QString defaultValue, QWidget *parent,
bool restart, int page, bool expansion)
: KUrlRequester(parent), defaultValue(defaultValue), expansion(expansion)
{
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorURLRequester::slotApply);
connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorURLRequester::slotSetDefaults);
connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorURLRequester::loadInitialValue);
connect(this, &KonfiguratorURLRequester::textChanged, ext, QOverload<>::of(&KonfiguratorExtension::setChanged));
loadInitialValue();
}
KonfiguratorURLRequester::~KonfiguratorURLRequester()
{
delete ext;
}
void KonfiguratorURLRequester::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
lineEdit()->setText(group.readEntry(ext->getConfigName(), defaultValue));
ext->setChanged(false);
}
void KonfiguratorURLRequester::slotApply(QObject *, QString configGroup, QString name)
{
KConfigGroup(krConfig, configGroup)
.writeEntry(name, expansion ? url().toDisplayString(QUrl::PreferLocalFile) : text());
}
void KonfiguratorURLRequester::slotSetDefaults(QObject *)
{
if (url().toDisplayString(QUrl::PreferLocalFile) != defaultValue)
lineEdit()->setText(defaultValue);
}
// KonfiguratorFontChooser class
///////////////////////////////
KonfiguratorFontChooser::KonfiguratorFontChooser(QString configGroup, QString name, QFont defaultValue,
QWidget *parent, bool restart, int page) : QWidget(parent),
defaultValue(defaultValue)
{
QHBoxLayout *layout = new QHBoxLayout(this);
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
- connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString)));
- connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*)));
- connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue()));
+ connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorFontChooser::slotApply);
+ connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorFontChooser::slotSetDefaults);
+ connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorFontChooser::loadInitialValue);
pLabel = new QLabel(this);
pLabel->setMinimumWidth(150);
layout->addWidget(pLabel);
pToolButton = new QToolButton(this);
- connect(pToolButton, SIGNAL(clicked()), this, SLOT(slotBrowseFont()));
+ connect(pToolButton, &QToolButton::clicked, this, &KonfiguratorFontChooser::slotBrowseFont);
pToolButton->setIcon(Icon("document-open"));
layout->addWidget(pToolButton);
loadInitialValue();
}
KonfiguratorFontChooser::~KonfiguratorFontChooser()
{
delete ext;
}
void KonfiguratorFontChooser::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
font = group.readEntry(ext->getConfigName(), defaultValue);
ext->setChanged(false);
setFont();
}
void KonfiguratorFontChooser::setFont()
{
pLabel->setFont(font);
pLabel->setText(font.family() + QString(", %1").arg(font.pointSize()));
}
void KonfiguratorFontChooser::slotApply(QObject *, QString configGroup, QString name)
{
KConfigGroup(krConfig, configGroup).writeEntry(name, font);
}
void KonfiguratorFontChooser::slotSetDefaults(QObject *)
{
font = defaultValue;
ext->setChanged();
setFont();
}
void KonfiguratorFontChooser::slotBrowseFont()
{
bool ok;
font = QFontDialog::getFont(&ok, font, this);
if (!ok) return; // cancelled by the user, and font is actually not changed (getFont returns the font we gave it)
ext->setChanged();
setFont();
}
// KonfiguratorComboBox class
///////////////////////////////
KonfiguratorComboBox::KonfiguratorComboBox(QString configGroup, QString name, QString defaultValue,
KONFIGURATOR_NAME_VALUE_PAIR *listIn, int listInLen, QWidget *parent,
bool restart, bool editable, int page) : QComboBox(parent),
defaultValue(defaultValue), listLen(listInLen)
{
list = new KONFIGURATOR_NAME_VALUE_PAIR[ listInLen ];
for (int i = 0; i != listLen; i++) {
list[i] = listIn[i];
addItem(list[i].text);
}
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
- connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString)));
- connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*)));
- connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue()));
+ connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorComboBox::slotApply);
+ connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorComboBox::slotSetDefaults);
+ connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorComboBox::loadInitialValue);
-// connect( this, SIGNAL(highlighted(int)), ext, SLOT(setChanged()) ); /* Removed because of startup combo failure */
- connect(this, SIGNAL(activated(int)), ext, SLOT(setChanged()));
- connect(this, SIGNAL(currentTextChanged(QString)), ext, SLOT(setChanged()));
+ //connect(this, &KonfiguratorComboBox::highlighted, ext, &KonfiguratorExtension::setChanged); /* Removed because of startup combo failure */
+ connect(this, QOverload::of(&KonfiguratorComboBox::activated), ext, QOverload<>::of(&KonfiguratorExtension::setChanged));
+ connect(this, &KonfiguratorComboBox::currentTextChanged, ext, QOverload<>::of(&KonfiguratorExtension::setChanged));
setEditable(editable);
loadInitialValue();
}
KonfiguratorComboBox::~KonfiguratorComboBox()
{
delete []list;
delete ext;
}
void KonfiguratorComboBox::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
QString select = group.readEntry(ext->getConfigName(), defaultValue);
selectEntry(select);
ext->setChanged(false);
}
void KonfiguratorComboBox::slotApply(QObject *, QString configGroup, QString name)
{
QString text = isEditable() ? lineEdit()->text() : currentText();
QString value = text;
for (int i = 0; i != listLen; i++)
if (list[i].text == text) {
value = list[i].value;
break;
}
KConfigGroup(krConfig, configGroup).writeEntry(name, value);
}
void KonfiguratorComboBox::selectEntry(QString entry)
{
for (int i = 0; i != listLen; i++)
if (list[i].value == entry) {
setCurrentIndex(i);
return;
}
if (isEditable())
lineEdit()->setText(entry);
else
setCurrentIndex(0);
}
void KonfiguratorComboBox::slotSetDefaults(QObject *)
{
selectEntry(defaultValue);
}
// KonfiguratorColorChooser class
///////////////////////////////
KonfiguratorColorChooser::KonfiguratorColorChooser(QString configGroup, QString name,
QColor defaultValue, QWidget *parent,
bool restart, ADDITIONAL_COLOR *addColPtr,
int addColNum, int page)
: QComboBox(parent), defaultValue(defaultValue), disableColorChooser(true)
{
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
- connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString)));
- connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*)));
- connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue()));
+ connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorColorChooser::slotApply);
+ connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorColorChooser::slotSetDefaults);
+ connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorColorChooser::loadInitialValue);
addColor(i18n("Custom color"), QColor(255, 255, 255));
addColor(i18nc("Default color", "Default"), defaultValue);
for (int i = 0; i != addColNum; i++) {
additionalColors.push_back(addColPtr[i]);
addColor(addColPtr[i].name, addColPtr[i].color);
}
addColor(i18n("Red"), Qt::red);
addColor(i18n("Green"), Qt::green);
addColor(i18n("Blue"), Qt::blue);
addColor(i18n("Cyan"), Qt::cyan);
addColor(i18n("Magenta"), Qt::magenta);
addColor(i18n("Yellow"), Qt::yellow);
addColor(i18n("Dark Red"), Qt::darkRed);
addColor(i18n("Dark Green"), Qt::darkGreen);
addColor(i18n("Dark Blue"), Qt::darkBlue);
addColor(i18n("Dark Cyan"), Qt::darkCyan);
addColor(i18n("Dark Magenta"), Qt::darkMagenta);
addColor(i18n("Dark Yellow"), Qt::darkYellow);
addColor(i18n("White"), Qt::white);
addColor(i18n("Light Gray"), Qt::lightGray);
addColor(i18n("Gray"), Qt::gray);
addColor(i18n("Dark Gray"), Qt::darkGray);
addColor(i18n("Black"), Qt::black);
- connect(this, SIGNAL(activated(int)), this, SLOT(slotCurrentChanged(int)));
+ connect(this, QOverload::of(&KonfiguratorColorChooser::activated), this, &KonfiguratorColorChooser::slotCurrentChanged);
loadInitialValue();
}
KonfiguratorColorChooser::~KonfiguratorColorChooser()
{
delete ext;
}
QPixmap KonfiguratorColorChooser::createPixmap(QColor color)
{
QPainter painter;
QPen pen;
int size = QFontMetrics(font()).height() * 3 / 4;
QRect rect(0, 0, size, size);
QPixmap pixmap(rect.width(), rect.height());
pen.setColor(Qt::black);
painter.begin(&pixmap);
QBrush brush(color);
painter.fillRect(rect, brush);
painter.setPen(pen);
painter.drawRect(rect);
painter.end();
pixmap.detach();
return pixmap;
}
void KonfiguratorColorChooser::addColor(QString text, QColor color)
{
addItem(createPixmap(color), text);
palette.push_back(color);
}
void KonfiguratorColorChooser::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
QString selected = group.readEntry(ext->getConfigName(), QString(""));
setValue(selected);
ext->setChanged(false);
}
void KonfiguratorColorChooser::setDefaultColor(QColor dflt)
{
defaultValue = dflt;
palette[1] = defaultValue;
setItemIcon(1, createPixmap(defaultValue));
if (currentIndex() == 1)
emit colorChanged();
}
void KonfiguratorColorChooser::changeAdditionalColor(int num, QColor color)
{
if (num < additionalColors.size()) {
palette[2+num] = color;
additionalColors[num].color = color;
setItemIcon(2 + num, createPixmap(color));
if (currentIndex() == 2 + num)
emit colorChanged();
}
}
void KonfiguratorColorChooser::setDefaultText(QString text)
{
setItemIcon(1, createPixmap(defaultValue));
setItemText(1, text);
}
void KonfiguratorColorChooser::slotApply(QObject *, QString configGroup, QString name)
{
KConfigGroup(krConfig, configGroup).writeEntry(name, getValue());
}
void KonfiguratorColorChooser::setValue(QString value)
{
disableColorChooser = true;
if (value.isEmpty()) {
setCurrentIndex(1);
customValue = defaultValue;
} else {
bool found = false;
for (int j = 0; j != additionalColors.size(); j++)
if (additionalColors[j].value == value) {
setCurrentIndex(2 + j);
found = true;
break;
}
if (! found) {
KConfigGroup colGroup(krConfig, ext->getConfigGroup());
colGroup.writeEntry("TmpColor", value);
QColor color = colGroup.readEntry("TmpColor", defaultValue);
customValue = color;
colGroup.deleteEntry("TmpColor");
setCurrentIndex(0);
for (int i = 2 + additionalColors.size(); i != palette.size(); i++)
if (palette[i] == color) {
setCurrentIndex(i);
break;
}
}
}
palette[0] = customValue;
setItemIcon(0, createPixmap(customValue));
ext->setChanged();
emit colorChanged();
disableColorChooser = false;
}
QString KonfiguratorColorChooser::getValue()
{
QColor color = palette[ currentIndex()];
if (currentIndex() == 1) /* it's the default value? */
return "";
else if (currentIndex() >= 2 && currentIndex() < 2 + additionalColors.size())
return additionalColors[ currentIndex() - 2 ].value;
else
return QString("%1,%2,%3").arg(color.red()).arg(color.green()).arg(color.blue());
}
bool KonfiguratorColorChooser::isValueRGB()
{
return !(currentIndex() >= 1 && currentIndex() < 2 + additionalColors.size());
}
void KonfiguratorColorChooser::slotSetDefaults(QObject *)
{
ext->setChanged();
setCurrentIndex(1);
emit colorChanged();
}
void KonfiguratorColorChooser::slotCurrentChanged(int number)
{
ext->setChanged();
if (number == 0 && !disableColorChooser) {
QColor color = QColorDialog::getColor(customValue, this);
if (color.isValid()) {
disableColorChooser = true;
customValue = color;
palette[0] = customValue;
setItemIcon(0, createPixmap(customValue));
disableColorChooser = false;
}
}
emit colorChanged();
}
QColor KonfiguratorColorChooser::getColor()
{
return palette[ currentIndex()];
}
// KonfiguratorListBox class
///////////////////////////////
KonfiguratorListBox::KonfiguratorListBox(QString configGroup, QString name, QStringList defaultValue,
QWidget *parent, bool restart, int page) : KrListWidget(parent),
defaultValue(defaultValue)
{
ext = new KonfiguratorExtension(this, configGroup, name, restart, page);
- connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString)));
- connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*)));
- connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue()));
+ connect(ext, &KonfiguratorExtension::applyAuto, this, &KonfiguratorListBox::slotApply);
+ connect(ext, &KonfiguratorExtension::setDefaultsAuto, this, &KonfiguratorListBox::slotSetDefaults);
+ connect(ext, &KonfiguratorExtension::setInitialValue, this, &KonfiguratorListBox::loadInitialValue);
loadInitialValue();
}
KonfiguratorListBox::~KonfiguratorListBox()
{
delete ext;
}
void KonfiguratorListBox::loadInitialValue()
{
KConfigGroup group(krConfig, ext->getConfigGroup());
setList(group.readEntry(ext->getConfigName(), defaultValue));
ext->setChanged(false);
}
void KonfiguratorListBox::slotApply(QObject *, QString configGroup, QString name)
{
KConfigGroup(krConfig, configGroup).writeEntry(name, list());
}
void KonfiguratorListBox::slotSetDefaults(QObject *)
{
if (list() != defaultValue) {
ext->setChanged();
setList(defaultValue);
}
}
void KonfiguratorListBox::setList(QStringList list)
{
clear();
addItems(list);
}
QStringList KonfiguratorListBox::list()
{
QStringList lst;
for (int i = 0; i != count(); i++)
lst += item(i)->text();
return lst;
}
void KonfiguratorListBox::addItem(const QString & item)
{
if (!list().contains(item)) {
KrListWidget::addItem(item);
ext->setChanged();
}
}
void KonfiguratorListBox::removeItem(const QString & item)
{
QList list = findItems(item, Qt::MatchExactly);
for (int i = 0; i != list.count(); i++)
delete list[ i ];
if (list.count())
ext->setChanged();
}
diff --git a/krusader/Konfigurator/krresulttable.cpp b/krusader/Konfigurator/krresulttable.cpp
index 02289831..53cdd4f5 100644
--- a/krusader/Konfigurator/krresulttable.cpp
+++ b/krusader/Konfigurator/krresulttable.cpp
@@ -1,396 +1,395 @@
/*****************************************************************************
* Copyright (C) 2005 Dirk Eschler *
* Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "krresulttable.h"
#include
// QtCore
#include
// QtGui
#include
#include
// QtWidgets
#include
#include
#include
#include "../krservices.h"
#include "../Archive/krarchandler.h"
using namespace std;
#define PS(x) _supported.contains(x)>0
KrResultTable::KrResultTable(QWidget* parent)
: QWidget(parent),
_numRows(1)
{
}
KrResultTable::~KrResultTable()
{
}
QGridLayout* KrResultTable::initTable()
{
_grid = new QGridLayout(this);
_grid->setColumnStretch(_numColumns - 1, 1); // stretch last column
_grid->setContentsMargins(0, 0, 0, 0);
_grid->setSpacing(0);
// +++ Build and add table header +++
int column = 0;
for (QStringList::Iterator it = _tableHeaders.begin(); it != _tableHeaders.end(); ++it) {
_label = new QLabel(*it, this);
_label->setContentsMargins(5, 5, 5, 5);
_grid->addWidget(_label, 0, column);
// Set font
QFont defFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
defFont.setPointSize(defFont.pointSize() - 1);
defFont.setBold(true);
_label->setFont(defFont);
++column;
}
return _grid;
}
void KrResultTable::adjustRow(QGridLayout* grid)
{
int i = 0;
QLayoutItem *child;
int col = 0;
while ((child = grid->itemAt(i)) != 0) {
// Add some space between columns
child->widget()->setMinimumWidth(child->widget()->sizeHint().width() + 15);
// Paint uneven rows in alternate color
if (((col / _numColumns) % 2)) {
child->widget()->setAutoFillBackground(true);
QPalette p = QGuiApplication::palette();
QPalette pal = child->widget()->palette();
pal.setColor(child->widget()->backgroundRole(), p.color(QPalette::Active, QPalette::AlternateBase));
child->widget()->setPalette(pal);
}
++i;
++col;
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
KrArchiverResultTable::KrArchiverResultTable(QWidget* parent)
: KrResultTable(parent)
{
_supported = KRarcHandler::supportedPackers(); // get list of available packers
Archiver* tar = new Archiver("tar", "http://www.gnu.org", PS("tar"), true, true);
Archiver* gzip = new Archiver("gzip", "http://www.gnu.org", PS("gzip"), true, true);
Archiver* bzip2 = new Archiver("bzip2", "http://www.gnu.org", PS("bzip2"), true, true);
Archiver* lzma = new Archiver("lzma", "http://tukaani.org/lzma", PS("lzma"), true, true);
Archiver* xz = new Archiver("xz", "http://tukaani.org/xz", PS("xz"), true, true);
Archiver* lha = new Archiver("lha", "http://www.gnu.org", PS("lha"), true, true);
Archiver* zip = new Archiver("zip", "http://www.info-zip.org", PS("zip"), true, false);
Archiver* unzip = new Archiver("unzip", "http://www.info-zip.org", PS("unzip"), false, true);
Archiver* arj = new Archiver("arj", "http://www.arjsoftware.com", PS("arj"), true, true);
Archiver* unarj = new Archiver("unarj", "http://www.arjsoftware.com", PS("unarj"), false, true);
Archiver* unace = new Archiver("unace", "http://www.winace.com", PS("unace"), false, true);
Archiver* rar = new Archiver("rar", "http://www.rarsoft.com", PS("rar"), true, true);
Archiver* unrar = new Archiver("unrar", "http://www.rarsoft.com", PS("unrar"), false, true);
Archiver* rpm = new Archiver("rpm", "http://www.gnu.org", PS("rpm"), false, true);
Archiver* dpkg = new Archiver("dpkg", "http://www.dpkg.org", PS("dpkg"), false, true);
Archiver* _7z = new Archiver("7z", "http://www.7-zip.org", PS("7z"), true, true);
// Special case: arj can unpack, but unarj is preferred
if (PS("arj") && PS("unarj"))
arj->setIsUnpacker(false);
if (PS("arj") && !PS("unarj"))
unarj->setNote(i18n("unarj not found, but arj found, which will be used for unpacking"));
// Special case: rar can unpack, but unrar is preferred
if (PS("rar") && PS("unrar"))
rar->setIsUnpacker(false);
// Special case: rpm needs cpio for unpacking
if (PS("rpm") && !PS("cpio"))
rpm->setNote(i18n("rpm found, but cpio not found which is required for unpacking"));
_tableHeaders.append(i18n("Name"));
_tableHeaders.append(i18n("Found"));
_tableHeaders.append(i18n("Packing"));
_tableHeaders.append(i18n("Unpacking"));
_tableHeaders.append(i18n("Note"));
_numColumns = _tableHeaders.size();
_grid = initTable();
addRow(tar, _grid);
addRow(gzip, _grid);
addRow(bzip2, _grid);
addRow(lzma, _grid);
addRow(xz, _grid);
addRow(lha, _grid);
addRow(zip, _grid);
addRow(unzip, _grid);
addRow(arj, _grid);
addRow(unarj, _grid);
addRow(unace, _grid);
addRow(rar, _grid);
addRow(unrar, _grid);
addRow(rpm, _grid);
addRow(dpkg, _grid);
addRow(_7z, _grid);
delete tar;
delete gzip;
delete bzip2;
delete lzma;
delete xz;
delete lha;
delete zip;
delete unzip;
delete arj;
delete unarj;
delete unace;
delete rar;
delete unrar;
delete rpm;
delete dpkg;
delete _7z;
}
KrArchiverResultTable::~KrArchiverResultTable()
{
}
bool KrArchiverResultTable::addRow(SearchObject* search, QGridLayout* grid)
{
Archiver* arch = dynamic_cast(search);
// Name column
_label = new KUrlLabel(arch->getWebsite(), arch->getSearchName(), this);
_label->setContentsMargins(5, 5, 5, 5);
_label->setAlignment(Qt::AlignTop);
grid->addWidget(_label, _numRows, 0);
- connect(_label, SIGNAL(leftClickedUrl(QString)),
- SLOT(website(QString)));
+ connect(dynamic_cast(_label), QOverload::of(&KUrlLabel::leftClickedUrl), this, &KrArchiverResultTable::website);
// Found column
_label = new QLabel(arch->getPath(), this);
_label->setContentsMargins(5, 5, 5, 5);
grid->addWidget(_label, _numRows, 1);
// Packing column
_label = new QLabel(this);
_label->setContentsMargins(5, 5, 5, 5);
_label->setAlignment(Qt::AlignTop);
if (arch->getIsPacker() && arch->getFound()) {
_label->setText(i18n("enabled"));
QPalette pal = _label->palette();
pal.setColor(_label->foregroundRole(), "darkgreen");
_label->setPalette(pal);
} else if (arch->getIsPacker() && !arch->getFound()) {
_label->setText(i18n("disabled"));
QPalette pal = _label->palette();
pal.setColor(_label->foregroundRole(), "red");
_label->setPalette(pal);
} else
_label->setText("");
grid->addWidget(_label, _numRows, 2);
// Unpacking column
_label = new QLabel(this);
_label->setContentsMargins(5, 5, 5, 5);
_label->setAlignment(Qt::AlignTop);
if (arch->getIsUnpacker() && arch->getFound()) {
_label->setText(i18n("enabled"));
QPalette pal = _label->palette();
pal.setColor(_label->foregroundRole(), "darkgreen");
_label->setPalette(pal);
} else if (arch->getIsUnpacker() && !arch->getFound()) {
_label->setText(i18n("disabled"));
QPalette pal = _label->palette();
pal.setColor(_label->foregroundRole(), "red");
_label->setPalette(pal);
} else
_label->setText("");
grid->addWidget(_label, _numRows, 3);
// Note column
_label = new QLabel(arch->getNote(), this);
_label->setContentsMargins(5, 5, 5, 5);
_label->setAlignment(Qt::AlignTop);
_label->setWordWrap(true); // wrap words
grid->addWidget(_label, _numRows, 4);
// Apply shared design elements
adjustRow(_grid);
// Ensure the last column takes more space
_label->setMinimumWidth(300);
++_numRows;
return true;
}
void KrArchiverResultTable::website(const QString& url)
{
(void) new KRun(QUrl(url), this);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
KrToolResultTable::KrToolResultTable(QWidget* parent)
: KrResultTable(parent)
{
_supported = KrServices::supportedTools(); // get list of available tools
QList vecDiff, vecMail, vecRename, vecChecksum;
Application* kdiff3 = new Application("kdiff3", "http://kdiff3.sourceforge.net/", KrServices::cmdExist("kdiff3"));
Application* kompare = new Application("kompare", "http://www.caffeinated.me.uk/kompare/", KrServices::cmdExist("kompare"));
Application* xxdiff = new Application("xxdiff", "http://xxdiff.sourceforge.net/", KrServices::cmdExist("xxdiff"));
Application* thunderbird = new Application("thunderbird", "http://www.mozilla.org/", KrServices::cmdExist("thunderbird"));
Application* kmail = new Application("kmail", "http://kmail.kde.org/", KrServices::cmdExist("kmail"));
Application* krename = new Application("krename", "http://www.krename.net/", KrServices::cmdExist("krename"));
Application* md5sum = new Application("md5sum", "http://www.gnu.org/software/textutils/textutils.html", KrServices::cmdExist("md5sum"));
vecDiff.push_back(kdiff3);
vecDiff.push_back(kompare);
vecDiff.push_back(xxdiff);
vecMail.push_back(thunderbird);
vecMail.push_back(kmail);
vecRename.push_back(krename);
vecChecksum.push_back(md5sum);
ApplicationGroup* diff = new ApplicationGroup(i18n("diff utility"), PS("DIFF"), vecDiff);
ApplicationGroup* mail = new ApplicationGroup(i18n("email client"), PS("MAIL"), vecMail);
ApplicationGroup* rename = new ApplicationGroup(i18n("batch renamer"), PS("RENAME"), vecRename);
ApplicationGroup* checksum = new ApplicationGroup(i18n("checksum utility"), PS("MD5"), vecChecksum);
_tableHeaders.append(i18n("Group"));
_tableHeaders.append(i18n("Tool"));
_tableHeaders.append(i18n("Found"));
_tableHeaders.append(i18n("Status"));
_numColumns = _tableHeaders.size();
_grid = initTable();
addRow(diff, _grid);
addRow(mail, _grid);
addRow(rename, _grid);
addRow(checksum, _grid);
delete thunderbird;
delete kmail;
delete kompare;
delete kdiff3;
delete xxdiff;
delete krename;
delete md5sum;
delete diff;
delete mail;
delete rename;
delete checksum;
}
KrToolResultTable::~KrToolResultTable()
{
}
bool KrToolResultTable::addRow(SearchObject* search, QGridLayout* grid)
{
ApplicationGroup* appGroup = dynamic_cast(search);
QList _apps = appGroup->getAppVec();
// Name column
_label = new QLabel(appGroup->getSearchName(), this);
_label->setContentsMargins(5, 5, 5, 5);
_label->setAlignment(Qt::AlignTop);
grid->addWidget(_label, _numRows, 0);
// Tool column
QWidget* toolBoxWidget = new QWidget(this);
QVBoxLayout * toolBox = new QVBoxLayout(toolBoxWidget);
for (QList::Iterator it = _apps.begin(); it != _apps.end(); ++it) {
KUrlLabel* l = new KUrlLabel((*it)->getWebsite(), (*it)->getAppName(), toolBoxWidget);
toolBox->addWidget(l);
l->setAlignment(Qt::AlignLeft | Qt::AlignTop);
l->setContentsMargins(5, 5, 5, 5);
connect(l, QOverload::of(&KUrlLabel::leftClickedUrl), this, &KrToolResultTable::website);
}
grid->addWidget(toolBoxWidget, _numRows, 1);
// Found column
QWidget* vboxWidget = new QWidget(this);
QVBoxLayout * vbox = new QVBoxLayout(vboxWidget);
for (QList::Iterator it = _apps.begin(); it != _apps.end(); ++it) {
_label = new QLabel((*it)->getPath(), vboxWidget);
_label->setContentsMargins(5, 5, 5, 5);
_label->setAlignment(Qt::AlignTop);
vbox->addWidget(_label);
}
grid->addWidget(vboxWidget, _numRows, 2);
// Status column
_label = new QLabel(this);
_label->setContentsMargins(5, 5, 5, 5);
_label->setAlignment(Qt::AlignTop);
if (appGroup->getFoundGroup()) {
_label->setText(i18n("enabled"));
QPalette pal = _label->palette();
pal.setColor(_label->foregroundRole(), "darkgreen");
_label->setPalette(pal);
} else {
_label->setText(i18n("disabled"));
QPalette pal = _label->palette();
pal.setColor(_label->foregroundRole(), "red");
_label->setPalette(pal);
}
grid->addWidget(_label, _numRows, 3);
// Apply shared design elements
adjustRow(_grid);
// Ensure the last column takes more space
_label->setMinimumWidth(300);
++_numRows;
return true;
}
void KrToolResultTable::website(const QString& url)
{
(void) new KRun(QUrl(url), this);
}
diff --git a/krusader/Locate/locate.cpp b/krusader/Locate/locate.cpp
index 37eb0659..6e1f4f41 100644
--- a/krusader/Locate/locate.cpp
+++ b/krusader/Locate/locate.cpp
@@ -1,692 +1,689 @@
/*****************************************************************************
* Copyright (C) 2004 Csaba Karai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "locate.h"
#include "../kractions.h"
#include "../krglobal.h"
#include "../filelisticon.h"
#include "../krslots.h"
#include "../krusaderview.h"
#include "../Panel/krpanel.h"
#include "../Panel/panelfunc.h"
#include "../GUI/krtreewidget.h"
#include "../defaults.h"
#include "../krservices.h"
#include "../FileSystem/filesystem.h"
#include "../FileSystem/virtualfilesystem.h"
#include "../KViewer/krviewer.h"
#include "../panelmanager.h"
// QtCore
#include
#include
#include
#include
// QtGui
#include
#include
#include
#include
#include
#include
// QtWidgets
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// these are the values that will exist in the menu
#define VIEW_ID 90
#define EDIT_ID 91
#define FIND_ID 92
#define FIND_NEXT_ID 93
#define FIND_PREV_ID 94
#define COPY_SELECTED_TO_CLIPBOARD 95
#define COMPARE_ID 96
//////////////////////////////////////////////////////////
class LocateListView : public KrTreeWidget
{
public:
explicit LocateListView(QWidget * parent) : KrTreeWidget(parent) {
setAlternatingRowColors(true);
}
void startDrag(Qt::DropActions supportedActs) Q_DECL_OVERRIDE {
Q_UNUSED(supportedActs);
QList urls;
QList list = selectedItems();
QListIterator it(list);
while (it.hasNext()) {
QTreeWidgetItem * item = it.next();
urls.push_back(QUrl::fromLocalFile(item->text(0)));
}
if (urls.count() == 0)
return;
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setImageData(FileListIcon("file").pixmap());
mimeData->setUrls(urls);
drag->setMimeData(mimeData);
drag->start();
}
};
KProcess * LocateDlg::updateProcess = 0;
LocateDlg * LocateDlg::LocateDialog = 0;
LocateDlg::LocateDlg(QWidget *parent) : QDialog(parent), isFeedToListBox(false)
{
setWindowTitle(i18n("Krusader::Locate"));
setWindowModality(Qt::NonModal);
QVBoxLayout *mainLayout = new QVBoxLayout;
setLayout(mainLayout);
QGridLayout *grid = new QGridLayout();
grid->setSpacing(6);
grid->setContentsMargins(11, 11, 11, 11);
QWidget *hboxWidget = new QWidget(this);
QHBoxLayout *hbox = new QHBoxLayout(hboxWidget);
hbox->setContentsMargins(0, 0, 0, 0);
QLabel *label = new QLabel(i18n("Search for:"), hboxWidget);
hbox->addWidget(label);
locateSearchFor = new KHistoryComboBox(false, hboxWidget);
locateSearchFor->setMinimumContentsLength(10);
hbox->addWidget(locateSearchFor);
label->setBuddy(locateSearchFor);
KConfigGroup group(krConfig, "Locate");
QStringList list = group.readEntry("Search For", QStringList());
locateSearchFor->setMaxCount(25); // remember 25 items
locateSearchFor->setHistoryItems(list);
locateSearchFor->setEditable(true);
locateSearchFor->setDuplicatesEnabled(false);
locateSearchFor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
locateSearchFor->lineEdit()->setFocus();
grid->addWidget(hboxWidget, 0, 0);
QWidget *hboxWidget2 = new QWidget(this);
QHBoxLayout * hbox2 = new QHBoxLayout(hboxWidget2);
hbox2->setContentsMargins(0, 0, 0, 0);
QSpacerItem* spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hbox2->addItem(spacer);
dontSearchInPath = new QCheckBox(i18n("Do not search in path"), hboxWidget2);
hbox2->addWidget(dontSearchInPath);
dontSearchInPath->setChecked(group.readEntry("Don't Search In Path", false));
existingFiles = new QCheckBox(i18n("Show only the existing files"), hboxWidget2);
existingFiles->setChecked(group.readEntry("Existing Files", false));
hbox2->addWidget(existingFiles);
caseSensitive = new QCheckBox(i18n("Case Sensitive"), hboxWidget2);
caseSensitive->setChecked(group.readEntry("Case Sensitive", false));
hbox2->addWidget(caseSensitive);
grid->addWidget(hboxWidget2, 1, 0);
QFrame *line1 = new QFrame(this);
line1->setFrameStyle(QFrame::HLine | QFrame::Sunken);
grid->addWidget(line1, 2, 0);
resultList = new LocateListView(this); // create the main container
resultList->setColumnCount(1);
resultList->setHeaderLabel(i18n("Results"));
resultList->setColumnWidth(0, QFontMetrics(resultList->font()).width("W") * 60);
KConfigGroup gl(krConfig, "Look&Feel");
resultList->setFont(gl.readEntry("Filelist Font", _FilelistFont));
resultList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
resultList->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
resultList->header()->setSortIndicatorShown(false);
resultList->setSortingEnabled(false);
resultList->setSelectionMode(QAbstractItemView::ExtendedSelection);
resultList->setDragEnabled(true);
- connect(resultList, SIGNAL(itemRightClicked(QTreeWidgetItem*,QPoint,int)),
- this, SLOT(slotRightClick(QTreeWidgetItem*,QPoint)));
- connect(resultList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
- this, SLOT(slotDoubleClick(QTreeWidgetItem*)));
- connect(resultList, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
- this, SLOT(slotDoubleClick(QTreeWidgetItem*)));
+ connect(resultList, &KrTreeWidget::itemRightClicked, this, &LocateDlg::slotRightClick);
+ connect(resultList, &KrTreeWidget::itemDoubleClicked, this, &LocateDlg::slotDoubleClick);
+ connect(resultList, &KrTreeWidget::itemActivated, this, &LocateDlg::slotDoubleClick);
grid->addWidget(resultList, 3, 0);
QFrame *line2 = new QFrame(this);
line2->setFrameStyle(QFrame::HLine | QFrame::Sunken);
grid->addWidget(line2, 4, 0);
mainLayout->addLayout(grid);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
mainLayout->addWidget(buttonBox);
locateButton = new QPushButton(i18n("Locate"));
locateButton->setIcon(Icon(QStringLiteral("system-search")));
locateButton->setDefault(true);
buttonBox->addButton(locateButton, QDialogButtonBox::ActionRole);
updateDbButton = new QPushButton(i18n("Update DB"));
updateDbButton->setIcon(Icon(QStringLiteral("view-refresh")));
buttonBox->addButton(updateDbButton, QDialogButtonBox::ActionRole);
feedStopButton = new QPushButton;
buttonBox->addButton(feedStopButton, QDialogButtonBox::ActionRole);
- connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
- connect(locateButton, SIGNAL(clicked()), this, SLOT(slotLocate()));
- connect(updateDbButton, SIGNAL(clicked()), this, SLOT(slotUpdateDb()));
- connect(feedStopButton, SIGNAL(clicked()), this, SLOT(slotFeedStop()));
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &LocateDlg::reject);
+ connect(locateButton, &QPushButton::clicked, this, &LocateDlg::slotLocate);
+ connect(updateDbButton, &QPushButton::clicked, this, &LocateDlg::slotUpdateDb);
+ connect(feedStopButton, &QPushButton::clicked, this, &LocateDlg::slotFeedStop);
updateButtons(false);
if (updateProcess) {
if (updateProcess->state() == QProcess::Running) {
- connect(updateProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(updateFinished()));
+ connect(updateProcess, QOverload::of(&KProcess::finished), this, &LocateDlg::updateFinished);
updateDbButton->setEnabled(false);
} else
updateFinished();
}
show();
LocateDialog = this;
}
void LocateDlg::slotFeedStop() /* The stop / feed to listbox button */
{
if (isFeedToListBox)
feedToListBox();
else
locateProc->kill();
}
void LocateDlg::slotUpdateDb() /* The Update DB button */
{
if (!updateProcess) {
KConfigGroup group(krConfig, "Locate");
updateProcess = new KProcess(); // don't set the parent to 'this'! That would cause this process to be deleted once the dialog is closed
*updateProcess << KrServices::fullPathName("updatedb");
*updateProcess << KShell::splitArgs(group.readEntry("UpdateDB Arguments"));
- connect(updateProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(updateFinished()));
+ connect(updateProcess, QOverload::of(&KProcess::finished), this, &LocateDlg::updateFinished);
updateProcess->start();
updateDbButton->setEnabled(false);
}
}
void LocateDlg::updateFinished()
{
delete updateProcess;
updateProcess = 0;
updateDbButton->setEnabled(true);
}
void LocateDlg::slotLocate() /* The locate button */
{
locateSearchFor->addToHistory(locateSearchFor->currentText());
QStringList list = locateSearchFor->historyItems();
KConfigGroup group(krConfig, "Locate");
group.writeEntry("Search For", list);
group.writeEntry("Don't Search In Path", dontSearchPath = dontSearchInPath->isChecked());
group.writeEntry("Existing Files", onlyExist = existingFiles->isChecked());
group.writeEntry("Case Sensitive", isCs = caseSensitive->isChecked());
if (!KrServices::cmdExist("locate")) {
KMessageBox::error(0,
i18n("Cannot start 'locate'. Check the 'Dependencies' page in konfigurator."));
return;
}
resultList->clear();
lastItem = 0;
remaining = "";
updateButtons(true);
isFeedToListBox = false;
resultList->setFocus();
qApp->processEvents(); //FIXME - what's this for ?
locateProc = new KProcess(this);
locateProc->setOutputChannelMode(KProcess::SeparateChannels); // default is forwarding to the parent channels
- connect(locateProc, SIGNAL(readyReadStandardOutput()), SLOT(processStdout()));
- connect(locateProc, SIGNAL(readyReadStandardError()), SLOT(processStderr()));
- connect(locateProc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(locateFinished()));
- connect(locateProc, SIGNAL(error(QProcess::ProcessError)), SLOT(locateError()));
+ connect(locateProc, &KProcess::readyReadStandardOutput, this, &LocateDlg::processStdout);
+ connect(locateProc, &KProcess::readyReadStandardError, this, &LocateDlg::processStderr);
+ connect(locateProc, QOverload::of(&KProcess::finished), this, &LocateDlg::locateFinished);
+ connect(locateProc, QOverload::of(&KProcess::error), this, &LocateDlg::locateError);
*locateProc << KrServices::fullPathName("locate");
if (!isCs)
*locateProc << "-i";
*locateProc << (pattern = locateSearchFor->currentText());
if (!pattern.startsWith('*'))
pattern = '*' + pattern;
if (!pattern.endsWith('*'))
pattern = pattern + '*';
collectedErr = "";
locateProc->start();
}
void LocateDlg::locateError()
{
if (locateProc->error() == QProcess::FailedToStart)
KMessageBox::error(krMainWindow, i18n("Error during the start of 'locate' process."));
}
void LocateDlg::locateFinished()
{
if (locateProc->exitStatus() != QProcess::NormalExit || locateProc->exitStatus()) {
if (!collectedErr.isEmpty())
KMessageBox::error(krMainWindow, i18n("Locate produced the following error message:\n\n%1", collectedErr));
}
if (resultList->topLevelItemCount() == 0) {
locateSearchFor->setFocus();
isFeedToListBox = false;
} else {
isFeedToListBox = true;
}
updateButtons(false);
}
void LocateDlg::processStdout()
{
remaining += QString::fromLocal8Bit(locateProc->readAllStandardOutput());
QStringList list = remaining.split('\n');
int items = list.size();
for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
if (--items == 0 && !remaining.endsWith('\n'))
remaining = *it;
else {
if (dontSearchPath) {
QRegExp regExp(pattern, isCs ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard);
QString fileName = (*it).trimmed();
if (fileName.endsWith(QLatin1String("/")) && fileName != "/") {
fileName.truncate(fileName.length() - 1);
}
fileName = fileName.mid(fileName.lastIndexOf('/') + 1);
if (!regExp.exactMatch(fileName))
continue;
}
if (onlyExist) {
KFileItem file(QUrl::fromLocalFile((*it).trimmed()));
if (!file.isReadable())
continue;
}
if (lastItem)
lastItem = new QTreeWidgetItem(resultList, lastItem);
else
lastItem = new QTreeWidgetItem(resultList);
lastItem->setText(0, *it);
}
}
}
void LocateDlg::processStderr()
{
collectedErr += QString::fromLocal8Bit(locateProc->readAllStandardError());
}
void LocateDlg::slotRightClick(QTreeWidgetItem *item, const QPoint &pos)
{
if (!item)
return;
// create the menu
QMenu popup;
popup.setTitle(i18nc("@title:menu", "Locate"));
QAction * actView = popup.addAction(i18n("View (F3)"));
QAction * actEdit = popup.addAction(i18n("Edit (F4)"));
QAction * actComp = popup.addAction(i18n("Compare by content (F10)"));
if (resultList->selectedItems().count() != 2)
actComp->setEnabled(false);
popup.addSeparator();
QAction * actFind = popup.addAction(i18n("Find (Ctrl+F)"));
QAction * actNext = popup.addAction(i18n("Find next (Ctrl+N)"));
QAction * actPrev = popup.addAction(i18n("Find previous (Ctrl+P)"));
popup.addSeparator();
QAction * actClip = popup.addAction(i18n("Copy selected to clipboard"));
QAction * result = popup.exec(pos);
int ret = -1;
if (result == actView)
ret = VIEW_ID;
else if (result == actEdit)
ret = EDIT_ID;
else if (result == actFind)
ret = FIND_ID;
else if (result == actNext)
ret = FIND_NEXT_ID;
else if (result == actPrev)
ret = FIND_PREV_ID;
else if (result == actClip)
ret = COPY_SELECTED_TO_CLIPBOARD;
else if (result == actComp)
ret = COMPARE_ID;
if (ret != - 1)
operate(item, ret);
}
void LocateDlg::slotDoubleClick(QTreeWidgetItem *item)
{
if (!item)
return;
QString dirName = item->text(0);
QString fileName;
if (!QDir(dirName).exists()) {
fileName = dirName.mid(dirName.lastIndexOf('/') + 1);
dirName.truncate(dirName.lastIndexOf('/'));
}
ACTIVE_FUNC->openUrl(QUrl::fromLocalFile(dirName), fileName);
QDialog::accept();
}
void LocateDlg::keyPressEvent(QKeyEvent *e)
{
if (KrGlobal::copyShortcut == QKeySequence(e->key() | e->modifiers())) {
operate(0, COPY_SELECTED_TO_CLIPBOARD);
e->accept();
return;
}
switch (e->key()) {
case Qt::Key_M :
if (e->modifiers() == Qt::ControlModifier) {
resultList->setFocus();
e->accept();
}
break;
case Qt::Key_F3 :
if (resultList->currentItem())
operate(resultList->currentItem(), VIEW_ID);
break;
case Qt::Key_F4 :
if (resultList->currentItem())
operate(resultList->currentItem(), EDIT_ID);
break;
case Qt::Key_F10 :
operate(0, COMPARE_ID);
break;
case Qt::Key_N :
if (e->modifiers() == Qt::ControlModifier)
operate(resultList->currentItem(), FIND_NEXT_ID);
break;
case Qt::Key_P :
if (e->modifiers() == Qt::ControlModifier)
operate(resultList->currentItem(), FIND_PREV_ID);
break;
case Qt::Key_F :
if (e->modifiers() == Qt::ControlModifier)
operate(resultList->currentItem(), FIND_ID);
break;
}
QDialog::keyPressEvent(e);
}
void LocateDlg::operate(QTreeWidgetItem *item, int task)
{
QUrl name;
if (item != 0)
name = QUrl::fromLocalFile(item->text(0));
switch (task) {
case VIEW_ID:
KrViewer::view(name, this); // view the file
break;
case EDIT_ID:
KrViewer::edit(name, this); // view the file
break;
case COMPARE_ID: {
QList list = resultList->selectedItems();
if (list.count() != 2)
break;
QUrl url1 = QUrl::fromLocalFile(list[ 0 ]->text(0));
QUrl url2 = QUrl::fromLocalFile(list[ 1 ]->text(0));
SLOTS->compareContent(url1,url2);
}
break;
case FIND_ID: {
KConfigGroup group(krConfig, "Locate");
long options = group.readEntry("Find Options", (long long)0);
QStringList list = group.readEntry("Find Patterns", QStringList());
QPointer dlg = new KFindDialog(this, options, list);
if (dlg->exec() != QDialog::Accepted) {
delete dlg;
return;
}
QString first;
if (list.count() != 0) {
first = list.first();
}
if (first != (findPattern = dlg->pattern())) {
list.push_front(dlg->pattern());
}
group.writeEntry("Find Options", (long long)(findOptions = dlg->options()));
group.writeEntry("Find Patterns", list);
if (!(findOptions & KFind::FromCursor) && resultList->topLevelItemCount())
resultList->setCurrentItem((findOptions & KFind::FindBackwards) ?
resultList->topLevelItem(resultList->topLevelItemCount() - 1) : resultList->topLevelItem(0));
findCurrentItem = resultList->currentItem();
if (find() && findCurrentItem) {
resultList->selectionModel()->clearSelection(); // HACK: QT 4 is not able to paint the focus frame because of a bug
resultList->setCurrentItem(findCurrentItem);
} else {
KMessageBox::information(this, i18n("Search string not found."));
}
resultList->scrollTo(resultList->currentIndex());
delete dlg;
}
break;
case FIND_NEXT_ID:
case FIND_PREV_ID: {
if (task == FIND_PREV_ID)
findOptions ^= KFind::FindBackwards;
findCurrentItem = resultList->currentItem();
nextLine();
if (find() && findCurrentItem) {
resultList->selectionModel()->clearSelection(); // HACK: QT 4 is not able to paint the focus frame because of a bug
resultList->setCurrentItem(findCurrentItem);
} else
KMessageBox::information(this, i18n("Search string not found."));
resultList->scrollTo(resultList->currentIndex());
if (task == FIND_PREV_ID)
findOptions ^= KFind::FindBackwards;
}
break;
case COPY_SELECTED_TO_CLIPBOARD: {
QList urls;
QTreeWidgetItemIterator it(resultList);
while (*it) {
if ((*it)->isSelected())
urls.push_back(QUrl::fromLocalFile((*it)->text(0)));
it++;
}
if (urls.count() == 0)
return;
QMimeData *mimeData = new QMimeData;
mimeData->setImageData(FileListIcon("file").pixmap());
mimeData->setUrls(urls);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
}
break;
}
}
void LocateDlg::nextLine()
{
if (findOptions & KFind::FindBackwards)
findCurrentItem = resultList->itemAbove(findCurrentItem);
else
findCurrentItem = resultList->itemBelow(findCurrentItem);
}
bool LocateDlg::find()
{
while (findCurrentItem) {
QString item = findCurrentItem->text(0);
if (findOptions & KFind::RegularExpression) {
if (item.contains(QRegExp(findPattern, ((findOptions & KFind::CaseSensitive) != 0) ? Qt::CaseSensitive : Qt::CaseInsensitive)))
return true;
} else {
if (item.contains(findPattern, ((findOptions & KFind::CaseSensitive) != 0) ? Qt::CaseSensitive : Qt::CaseInsensitive))
return true;
}
nextLine();
}
return false;
}
void LocateDlg::feedToListBox()
{
VirtualFileSystem virtFilesystem;
virtFilesystem.scanDir(QUrl::fromLocalFile(QStringLiteral("/")));
KConfigGroup group(krConfig, "Locate");
int listBoxNum = group.readEntry("Feed To Listbox Counter", 1);
QString queryName;
do {
queryName = i18n("Locate results") + QString(" %1").arg(listBoxNum++);
} while (virtFilesystem.getFileItem(queryName) != 0);
group.writeEntry("Feed To Listbox Counter", listBoxNum);
KConfigGroup ga(krConfig, "Advanced");
if (ga.readEntry("Confirm Feed to Listbox", _ConfirmFeedToListbox)) {
bool ok;
queryName = QInputDialog::getText(this, i18n("Query Name"), i18n("Here you can name the file collection:"),
QLineEdit::Normal, queryName, &ok);
if (! ok)
return;
}
QList urlList;
QTreeWidgetItemIterator it(resultList);
while (*it) {
QTreeWidgetItem * item = *it;
urlList.push_back(QUrl::fromLocalFile(item->text(0)));
it++;
}
QUrl url = QUrl(QStringLiteral("virt:/") + queryName);
virtFilesystem.refresh(url); // create directory if it does not exist
virtFilesystem.addFiles(urlList);
//ACTIVE_FUNC->openUrl(url);
ACTIVE_MNG->slotNewTab(url);
accept();
}
void LocateDlg::reset()
{
locateSearchFor->lineEdit()->setFocus();
locateSearchFor->lineEdit()->selectAll();
}
void LocateDlg::updateButtons(bool locateIsRunning)
{
locateButton->setEnabled(!locateIsRunning);
if (locateIsRunning) {
feedStopButton->setEnabled(true);
feedStopButton->setText(i18n("Stop"));
feedStopButton->setIcon(Icon(QStringLiteral("process-stop")));
} else {
if (resultList->topLevelItemCount() == 0) {
feedStopButton->setEnabled(false);
feedStopButton->setText(i18n("Stop"));
feedStopButton->setIcon(Icon(QStringLiteral("process-stop")));
} else {
feedStopButton->setEnabled(true);
feedStopButton->setText(i18n("Feed to listbox"));
feedStopButton->setIcon(Icon(QStringLiteral("list-add")));
}
}
}
diff --git a/krusader/MountMan/kmountmangui.cpp b/krusader/MountMan/kmountmangui.cpp
index dc49ad92..3cb0ec82 100644
--- a/krusader/MountMan/kmountmangui.cpp
+++ b/krusader/MountMan/kmountmangui.cpp
@@ -1,530 +1,526 @@
/*****************************************************************************
* Copyright (C) 2000 Shie Erlich *
* Copyright (C) 2000 Rafi Yanai *
* Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] *
* *
* This file is part of Krusader [https://krusader.org]. *
* *
* Krusader 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 2 of the License, or *
* (at your option) any later version. *
* *
* Krusader 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 Krusader. If not, see [http://www.gnu.org/licenses/]. *
*****************************************************************************/
#include "kmountmangui.h"
#include "../krglobal.h"
#include "../icon.h"
#include "../Dialogs/krspecialwidgets.h"
#include "../defaults.h"
#include "../FileSystem/filesystem.h"
// QtCore
#include
#include
#include
// QtGui
#include
#include