diff --git a/iso/iso.h b/iso/iso.h index 411e5a4b..8d49e1b8 100644 --- a/iso/iso.h +++ b/iso/iso.h @@ -1,59 +1,59 @@ /***************************************************************************** * Copyright (C) 2000 David Faure * * Copyright (C) 2002 Szombathelyi György * * Copyright (C) 2003 Leo Savernik * * Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] * * * * This file is heavily based on ktar from kdelibs * * * * 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 ISO_H #define ISO_H // QtCore #include #include #include #include "kisofile.h" class KIso; class kio_isoProtocol : public KIO::SlaveBase { public: kio_isoProtocol(const QByteArray &pool, const QByteArray &app); virtual ~kio_isoProtocol(); - virtual void listDir(const QUrl &url) Q_DECL_OVERRIDE; - virtual void stat(const QUrl &url) Q_DECL_OVERRIDE; - virtual void get(const QUrl &url) Q_DECL_OVERRIDE; + virtual void listDir(const QUrl &url) override; + virtual void stat(const QUrl &url) override; + virtual void get(const QUrl &url) override; protected: void getFile(const KIsoFile *isoFileEntry, const QString &path); void createUDSEntry(const KArchiveEntry * isoEntry, KIO::UDSEntry & entry); bool checkNewFile(QString fullPath, QString & path, int startsec); QString getPath(const QUrl &url); KIso * m_isoFile; time_t m_mtime; int m_mode; }; #endif diff --git a/iso/kiso.h b/iso/kiso.h index 64f6e139..0b5ab6f8 100644 --- a/iso/kiso.h +++ b/iso/kiso.h @@ -1,124 +1,124 @@ /***************************************************************************** * Copyright (C) 2000 David Faure * * Copyright (C) 2002 Szombathelyi György * * Copyright (C) 2003 Leo Savernik * * Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] * * * * This file is heavily based on ktar from kdelibs * * * * 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 KISO_H #define KISO_H // QtCore #include #include #include #include "../krusader/krdebuglogger.h" #include "kisofile.h" #include "kisodirectory.h" /** * @short A class for reading (optionally compressed) iso9660 files. */ class KIso : public KArchive { public: /** * Creates an instance that operates on the given filename. * using the compression filter associated to given mimetype. * * @param filename is a local path (e.g. "/home/weis/myfile.tgz") * @param mimetype "application/x-gzip" or "application/x-bzip2" * Do not use application/x-tgz or so. Only the compression layer ! * If the mimetype is omitted, it will be determined from the filename. */ explicit KIso(const QString& filename, const QString & mimetype = QString()); /** * Creates an instance that operates on the given device. * The device can be compressed (KFilterDev) or not (QFile, etc.). * WARNING: don't assume that giving a QFile here will decompress the file, * in case it's compressed! */ explicit KIso(QIODevice * dev); /** * If the .iso is still opened, then it will be * closed automatically by the destructor. */ virtual ~KIso(); /** * The name of the os file, as passed to the constructor * Null if you used the QIODevice constructor. */ QString fileName() { return m_filename; } bool writeDir(const QString& , const QString& , const QString&, mode_t, time_t, time_t, time_t); bool writeSymLink(const QString &, const QString &, const QString &, const QString &, mode_t, time_t, time_t, time_t); bool prepareWriting(const QString& , const QString& , const QString& , qint64, mode_t, time_t, time_t, time_t); bool finishWriting(qint64); void setStartSec(int startsec) { m_startsec = startsec; } int startSec() { return m_startsec; } bool showhidden, showrr; int level, joliet; KIsoDirectory *dirent; protected: /** * Opens the archive for reading. * Parses the directory listing of the archive * and creates the KArchiveDirectory/KArchiveFile entries. * */ void readParams(); - virtual bool openArchive(QIODevice::OpenMode mode) Q_DECL_OVERRIDE; - virtual bool closeArchive() Q_DECL_OVERRIDE; - virtual bool doWriteDir(const QString&, const QString&, const QString&, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) Q_DECL_OVERRIDE; - virtual bool doWriteSymLink(const QString &, const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) Q_DECL_OVERRIDE; - virtual bool doPrepareWriting(const QString& , const QString& , const QString& , qint64, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) Q_DECL_OVERRIDE; - virtual bool doFinishWriting(qint64) Q_DECL_OVERRIDE; + virtual bool openArchive(QIODevice::OpenMode mode) override; + virtual bool closeArchive() override; + virtual bool doWriteDir(const QString&, const QString&, const QString&, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) override; + virtual bool doWriteSymLink(const QString &, const QString &, const QString &, const QString &, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) override; + virtual bool doPrepareWriting(const QString& , const QString& , const QString& , qint64, mode_t, const QDateTime &, const QDateTime &, const QDateTime &) override; + virtual bool doFinishWriting(qint64) override; private: /** * @internal */ void addBoot(struct el_torito_boot_descriptor* bootdesc); void prepareDevice(const QString & filename, const QString & mimetype, bool forced = false); int m_startsec; QString m_filename; protected: - virtual void virtual_hook(int id, void* data) Q_DECL_OVERRIDE; + virtual void virtual_hook(int id, void* data) override; private: class KIsoPrivate; KIsoPrivate * d; }; #endif diff --git a/iso/qfilehack.h b/iso/qfilehack.h index dc723be6..f325243a 100644 --- a/iso/qfilehack.h +++ b/iso/qfilehack.h @@ -1,41 +1,41 @@ /***************************************************************************** * Copyright (C) 2002 Szombathelyi György * * Copyright (C) 2004-2019 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 QFILEHACK_H #define QFILEHACK_H // QtCore #include #include /** * Qt thinks if a file is not S_IFREG, you cannot seek in it. * It's false (what about block devices for example ?) */ class QFileHack : public QFile { public: QFileHack(); explicit QFileHack(const QString & name); ~QFileHack(); - virtual bool open(QFile::OpenMode m) Q_DECL_OVERRIDE; + virtual bool open(QFile::OpenMode m) override; }; #endif diff --git a/krArc/krarc.cpp b/krArc/krarc.cpp index 9717886c..331a4aea 100644 --- a/krArc/krarc.cpp +++ b/krArc/krarc.cpp @@ -1,1938 +1,1938 @@ /***************************************************************************** * Copyright (C) 2003 Rafi Yanai * * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2004-2019 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 "krarc.h" #include "../krusader/defaults.h" // QtCore #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../krusader/compat.h" #define MAX_IPC_SIZE (1024*32) #define TRIES_WITH_PASSWORDS 3 using namespace KIO; extern "C" { #ifdef KRARC_ENABLED /* This codec is for being able to handle files which encoding differs from the current locale. * * Unfortunately QProcess requires QString parameters for arguments which are encoded to Local8Bit * If we want to use unzip with ISO-8852-2 when the current locale is UTF-8, it will cause problems. * * Workaround: * 1. encode the QString to QByteArray ( according to the selected remote encoding, ISO-8852-2 ) * 2. encode QByteArray to QString again * unicode 0xE000-0xF7FF is for private use * the byte array is mapped to 0xE000-0xE0FF unicodes * 3. KrArcCodec maps 0xE000-0xE0FF to 0x0000-0x00FF, while calls the default encoding routine * for other unicodes. */ class KrArcCodec : public QTextCodec { public: KrArcCodec(QTextCodec * codec) : originalCodec(codec) {} ~KrArcCodec() override = default; - QByteArray name() const Q_DECL_OVERRIDE { + QByteArray name() const override { return originalCodec->name(); } - QList aliases() const Q_DECL_OVERRIDE { + QList aliases() const override { return originalCodec->aliases(); } - int mibEnum() const Q_DECL_OVERRIDE { + int mibEnum() const override { return originalCodec->mibEnum(); } protected: - QString convertToUnicode(const char *in, int length, ConverterState *state) const Q_DECL_OVERRIDE { + QString convertToUnicode(const char *in, int length, ConverterState *state) const override { return originalCodec->toUnicode(in, length, state); } - QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const Q_DECL_OVERRIDE { + QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const override { // the QByteArray is embedded into the unicode charset (QProcess hell) QByteArray result; for (int i = 0; i != length; i++) { if (((in[ i ].unicode()) & 0xFF00) == 0xE000) // map 0xE000-0xE0FF to 0x0000-0x00FF result.append((char)(in[ i ].unicode() & 0xFF)); else result.append(originalCodec->fromUnicode(in + i, 1, state)); } return result; } private: QTextCodec * originalCodec; } *krArcCodec; #define SET_KRCODEC QTextCodec *origCodec = QTextCodec::codecForLocale(); \ QTextCodec::setCodecForLocale( krArcCodec ); #define RESET_KRCODEC QTextCodec::setCodecForLocale( origCodec ); #endif // KRARC_ENABLED class DummySlave : public KIO::SlaveBase { public: DummySlave(const QByteArray &pool_socket, const QByteArray &app_socket) : SlaveBase("kio_krarc", pool_socket, app_socket) { error((int)ERR_SLAVE_DEFINED, QString("krarc is disabled.")); } }; int Q_DECL_EXPORT kdemain(int argc, char **argv) { if (argc != 4) { qWarning() << "Usage: kio_krarc protocol domain-socket1 domain-socket2" << endl; exit(-1); } // At least, that fixes the empty name in the warning that says: Please fix the "" KIO slave // There is more information in https://bugs.kde.org/show_bug.cgi?id=384653 QCoreApplication app(argc, argv); app.setApplicationName(QStringLiteral("kio_krarc")); #ifdef KRARC_ENABLED kio_krarcProtocol slave(argv[2], argv[3]); #else DummySlave slave(argv[2], argv[3]); #endif slave.dispatchLoop(); return 0; } } // extern "C" #ifdef KRARC_ENABLED kio_krarcProtocol::kio_krarcProtocol(const QByteArray &pool_socket, const QByteArray &app_socket) : SlaveBase("kio_krarc", pool_socket, app_socket), archiveChanged(true), arcFile(nullptr), extArcReady(false), password(QString()), krConf("krusaderrc"), codec(nullptr) { KRFUNC; confGrp = KConfigGroup(&krConf, "Dependencies"); KConfigGroup group(&krConf, "General"); QString tmpDirPath = group.readEntry("Temp Directory", _TempDirectory); QDir tmpDir(tmpDirPath); if(!tmpDir.exists()) { for (int i = 1 ; i != -1 ; i = tmpDirPath.indexOf('/', i + 1)) QDir().mkdir(tmpDirPath.left(i)); QDir().mkdir(tmpDirPath); } arcTempDir = tmpDirPath + DIR_SEPARATOR; QString dirName = "krArc" + QDateTime::currentDateTime().toString(Qt::ISODate); dirName.replace(QRegExp(":"), "_"); tmpDir.mkdir(dirName); arcTempDir = arcTempDir + dirName + DIR_SEPARATOR; krArcCodec = new KrArcCodec(QTextCodec::codecForLocale()); } /* ---------------------------------------------------------------------------------- */ kio_krarcProtocol::~kio_krarcProtocol() { KRFUNC; // delete the temp directory KProcess proc; proc << fullPathName("rm") << "-rf" << arcTempDir; proc.start(); proc.waitForFinished(); } /* ---------------------------------------------------------------------------------- */ bool kio_krarcProtocol::checkWriteSupport() { KRFUNC; krConf.reparseConfiguration(); if (KConfigGroup(&krConf, "kio_krarc").readEntry("EnableWrite", false)) return true; else { error(ERR_UNSUPPORTED_ACTION, i18n("krarc: write support is disabled.\n" "You can enable it on the 'Archives' page in Konfigurator.")); return false; } } void kio_krarcProtocol::receivedData(KProcess *, QByteArray &d) { KRFUNC; const QByteArray& buf(d); data(buf); processedSize(d.length()); decompressedLen += d.length(); } void kio_krarcProtocol::mkdir(const QUrl &url, int permissions) { KRFUNC; const QString path = getPath(url); KRDEBUG(path); if (!checkWriteSupport()) return; // In case of KIO::mkpath call there is a mkdir call for every path element. // Therefore the path all the way up to our archive needs to be checked for existence // and reported as success. if (QDir().exists(path)) { finished(); return; } if (!setArcFile(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, path); return; } if (newArchiveURL && !initDirDict(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, path); return; } if (putCmd.isEmpty()) { error(ERR_UNSUPPORTED_ACTION, i18n("Creating directories is not supported with %1 archives", arcType)); return; } const QString arcFilePath = getPath(arcFile->url()); if (arcType == "arj" || arcType == "lha") { QString arcDir = path.mid(arcFilePath.length()); if (arcDir.right(1) != DIR_SEPARATOR) arcDir = arcDir + DIR_SEPARATOR; if (dirDict.find(arcDir) == dirDict.end()) addNewDir(arcDir); finished(); return; } QString arcDir = findArcDirectory(url); QString tempDir = arcDir.mid(1) + path.mid(path.lastIndexOf(DIR_SEPARATOR) + 1); if (tempDir.right(1) != DIR_SEPARATOR) tempDir = tempDir + DIR_SEPARATOR; if (permissions == -1) permissions = 0777; //set default permissions QByteArray arcTempDirEnc = arcTempDir.toLocal8Bit(); for (int i = 0;i < tempDir.length() && i >= 0; i = tempDir.indexOf(DIR_SEPARATOR, i + 1)) { QByteArray newDirs = encodeString(tempDir.left(i)); newDirs.prepend(arcTempDirEnc); QT_MKDIR(newDirs, permissions); } if (tempDir.endsWith(DIR_SEPARATOR)) tempDir.truncate(tempDir.length() - 1); // pack the directory KrLinecountingProcess proc; proc << putCmd << arcFilePath << localeEncodedString(tempDir); infoMessage(i18n("Creating %1...", url.fileName())); QDir::setCurrent(arcTempDir); SET_KRCODEC proc.start(); RESET_KRCODEC proc.waitForFinished(); // delete the temp directory QDir().rmdir(arcTempDir); if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) { error(ERR_CANNOT_WRITE, path + "\n\n" + proc.getErrorMsg()); return; } // force a refresh of archive information initDirDict(url, true); finished(); } void kio_krarcProtocol::put(const QUrl &url, int permissions, KIO::JobFlags flags) { KRFUNC; KRDEBUG(getPath(url)); if (!checkWriteSupport()) return; bool overwrite = !!(flags & KIO::Overwrite); bool resume = !!(flags & KIO::Resume); if (!setArcFile(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (newArchiveURL && !initDirDict(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (putCmd.isEmpty()) { error(ERR_UNSUPPORTED_ACTION, i18n("Writing to %1 archives is not supported", arcType)); return; } if (!overwrite && findFileEntry(url)) { error(ERR_FILE_ALREADY_EXIST, getPath(url)); return; } QString arcDir = findArcDirectory(url); if (arcDir.isEmpty()) KRDEBUG("arcDir is empty."); QString tempFile = arcDir.mid(1) + getPath(url).mid(getPath(url).lastIndexOf(DIR_SEPARATOR) + 1); QString tempDir = arcDir.mid(1); if (tempDir.right(1) != DIR_SEPARATOR) tempDir = tempDir + DIR_SEPARATOR; if (permissions == -1) permissions = 0777; //set default permissions QByteArray arcTempDirEnc = arcTempDir.toLocal8Bit(); for (int i = 0;i < tempDir.length() && i >= 0; i = tempDir.indexOf(DIR_SEPARATOR, i + 1)) { QByteArray newDirs = encodeString(tempDir.left(i)); newDirs.prepend(arcTempDirEnc); QT_MKDIR(newDirs, 0755); } int fd; if (resume) { QByteArray ba = encodeString(tempFile); ba.prepend(arcTempDirEnc); fd = QT_OPEN(ba, O_RDWR); // append if resuming QT_LSEEK(fd, 0, SEEK_END); // Seek to end } else { // WABA: Make sure that we keep writing permissions ourselves, // otherwise we can be in for a surprise on NFS. mode_t initialMode; if (permissions != -1) initialMode = permissions | S_IWUSR | S_IRUSR; else initialMode = 0666; QByteArray ba = encodeString(tempFile); ba.prepend(arcTempDirEnc); fd = QT_OPEN(ba, O_CREAT | O_TRUNC | O_WRONLY, initialMode); } QByteArray buffer; int readResult; bool isIncomplete = false; do { dataReq(); readResult = readData(buffer); auto bytesWritten = ::write(fd, buffer.data(), buffer.size()); if (bytesWritten < buffer.size()) { isIncomplete = true; break; } } while (readResult > 0); ::close(fd); if (isIncomplete) { error(ERR_CANNOT_WRITE, getPath(url)); return; } // pack the file KrLinecountingProcess proc; proc << putCmd << getPath(arcFile->url()) << localeEncodedString(tempFile); infoMessage(i18n("Packing %1...", url.fileName())); QDir::setCurrent(arcTempDir); SET_KRCODEC proc.start(); RESET_KRCODEC proc.waitForFinished(); // remove the files QDir().rmdir(arcTempDir); if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) { error(ERR_CANNOT_WRITE, getPath(url) + "\n\n" + proc.getErrorMsg()); return; } // force a refresh of archive information initDirDict(url, true); finished(); } void kio_krarcProtocol::get(const QUrl &url) { KRFUNC; get(url, TRIES_WITH_PASSWORDS); } void kio_krarcProtocol::get(const QUrl &url, int tries) { KRFUNC; KRDEBUG(getPath(url)); bool decompressToFile = false; if (!setArcFile(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (newArchiveURL && !initDirDict(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (getCmd.isEmpty()) { error(ERR_UNSUPPORTED_ACTION, i18n("Retrieving data from %1 archives is not supported", arcType)); return; } UDSEntry* entry = findFileEntry(url); if (!entry) { error(KIO::ERR_DOES_NOT_EXIST, getPath(url)); return; } if (KFileItem(*entry, url).isDir()) { error(KIO::ERR_IS_DIRECTORY, getPath(url)); return; } KIO::filesize_t expectedSize = KFileItem(*entry, url).size(); // for RPM files extract the cpio file first if (!extArcReady && arcType == "rpm") { KrLinecountingProcess cpio; cpio << "rpm2cpio" << getPath(arcFile->url(), QUrl::StripTrailingSlash); cpio.setStandardOutputFile(arcTempDir + "contents.cpio"); cpio.start(); cpio.waitForFinished(); if (cpio.exitStatus() != QProcess::NormalExit || !checkStatus(cpio.exitCode())) { error(ERR_CANNOT_READ, getPath(url) + "\n\n" + cpio.getErrorMsg()); return; } extArcReady = true; } // for DEB files extract the tar file first if (!extArcReady && arcType == "deb") { KrLinecountingProcess dpkg; dpkg << cmd << "--fsys-tarfile" << getPath(arcFile->url(), QUrl::StripTrailingSlash); dpkg.setStandardOutputFile(arcTempDir + "contents.cpio"); dpkg.start(); dpkg.waitForFinished(); if (dpkg.exitStatus() != QProcess::NormalExit || !checkStatus(dpkg.exitCode())) { error(ERR_CANNOT_READ, getPath(url) + "\n\n" + dpkg.getErrorMsg()); return; } extArcReady = true; } // Use the external unpacker to unpack the file QString file = getPath(url).mid(getPath(arcFile->url()).length() + 1); KrLinecountingProcess proc; if (extArcReady) { proc << getCmd << arcTempDir + "contents.cpio" << '*' + localeEncodedString(file); } else if (arcType == "arj" || arcType == "ace" || arcType == "7z") { proc << getCmd << getPath(arcFile->url(), QUrl::StripTrailingSlash) << localeEncodedString(file); if (arcType == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! proc.setStandardInputFile("/dev/ptmx"); file = url.fileName(); decompressToFile = true; } else { decompressedLen = 0; // Determine the mimetype of the file to be retrieved, and emit it. // This is mandatory in all slaves (for KRun/BrowserRun to work). QMimeDatabase db; QMimeType mt = db.mimeTypeForFile(arcTempDir + file); if (mt.isValid()) emit mimeType(mt.name()); QString escapedFilename = file; if(arcType == "zip") // left bracket needs to be escaped escapedFilename.replace('[', "[[]"); proc << getCmd << getPath(arcFile->url()); if (arcType != "gzip" && arcType != "bzip2" && arcType != "lzma" && arcType != "xz") proc << localeEncodedString(escapedFilename); connect(&proc, &KrLinecountingProcess::newOutputData, this, &kio_krarcProtocol::receivedData); proc.setMerge(false); } infoMessage(i18n("Unpacking %1...", url.fileName())); // change the working directory to our arcTempDir QDir::setCurrent(arcTempDir); SET_KRCODEC proc.setTextModeEnabled(false); proc.start(); RESET_KRCODEC proc.waitForFinished(); if (!extArcReady && !decompressToFile) { if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode()) || (arcType != "bzip2" && arcType != "lzma" && arcType != "xz" && expectedSize != decompressedLen)) { if (encrypted && tries) { invalidatePassword(); get(url, tries - 1); return; } error(KIO::ERR_ACCESS_DENIED, getPath(url) + "\n\n" + proc.getErrorMsg()); return; } } else { if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode()) || !QFileInfo(arcTempDir + file).exists()) { if (decompressToFile) QFile(arcTempDir + file).remove(); if (encrypted && tries) { invalidatePassword(); get(url, tries - 1); return; } error(KIO::ERR_ACCESS_DENIED, getPath(url)); return; } // the following block is ripped from KDE file KIO::Slave // $Id: krarc.cpp,v 1.43 2007/01/13 13:39:51 ckarai Exp $ QByteArray _path(QFile::encodeName(arcTempDir + file)); QT_STATBUF buff; if (QT_LSTAT(_path.data(), &buff) == -1) { if (errno == EACCES) error(KIO::ERR_ACCESS_DENIED, getPath(url)); else error(KIO::ERR_DOES_NOT_EXIST, getPath(url)); return; } if (S_ISDIR(buff.st_mode)) { error(KIO::ERR_IS_DIRECTORY, getPath(url)); return; } if (!S_ISREG(buff.st_mode)) { error(KIO::ERR_CANNOT_OPEN_FOR_READING, getPath(url)); return; } int fd = QT_OPEN(_path.data(), O_RDONLY); if (fd < 0) { error(KIO::ERR_CANNOT_OPEN_FOR_READING, getPath(url)); return; } // Determine the mimetype of the file to be retrieved, and emit it. // This is mandatory in all slaves (for KRun/BrowserRun to work). QMimeDatabase db; QMimeType mt = db.mimeTypeForFile(arcTempDir + file); if (mt.isValid()) emit mimeType(mt.name()); KIO::filesize_t processed_size = 0; QString resumeOffset = metaData("resume"); if (!resumeOffset.isEmpty()) { bool ok; KIO::fileoffset_t offset = resumeOffset.toLongLong(&ok); if (ok && (offset > 0) && (offset < buff.st_size)) { if (QT_LSEEK(fd, offset, SEEK_SET) == offset) { canResume(); processed_size = offset; } } } totalSize(buff.st_size); char buffer[ MAX_IPC_SIZE ]; while (1) { int n = ::read(fd, buffer, MAX_IPC_SIZE); if (n == -1) { if (errno == EINTR) continue; error(KIO::ERR_CANNOT_READ, getPath(url)); ::close(fd); return; } if (n == 0) break; // Finished { QByteArray array = QByteArray::fromRawData(buffer, n); data(array); } processed_size += n; } data(QByteArray()); ::close(fd); processedSize(buff.st_size); finished(); if (decompressToFile) QFile(arcTempDir + file).remove(); return; } // send empty buffer to mark EOF data(QByteArray()); finished(); } void kio_krarcProtocol::del(QUrl const & url, bool isFile) { KRFUNC; KRDEBUG(getPath(url)); if (!checkWriteSupport()) return; if (!setArcFile(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (newArchiveURL && !initDirDict(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (delCmd.isEmpty()) { error(ERR_UNSUPPORTED_ACTION, i18n("Deleting files from %1 archives is not supported", arcType)); return; } if (!findFileEntry(url)) { if ((arcType != "arj" && arcType != "lha") || isFile) { error(KIO::ERR_DOES_NOT_EXIST, getPath(url)); return; } } QString file = getPath(url).mid(getPath(arcFile->url()).length() + 1); if (!isFile && file.right(1) != DIR_SEPARATOR) { if (arcType == "zip") file = file + DIR_SEPARATOR; } KrLinecountingProcess proc; proc << delCmd << getPath(arcFile->url()) << localeEncodedString(file); infoMessage(i18n("Deleting %1...", url.fileName())); SET_KRCODEC proc.start(); RESET_KRCODEC proc.waitForFinished(); if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) { error(ERR_CANNOT_WRITE, getPath(url) + "\n\n" + proc.getErrorMsg()); return; } // force a refresh of archive information initDirDict(url, true); finished(); } void kio_krarcProtocol::stat(const QUrl &url) { KRFUNC; KRDEBUG(getPath(url)); if (!setArcFile(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (newArchiveURL && !initDirDict(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (listCmd.isEmpty()) { error(ERR_UNSUPPORTED_ACTION, i18n("Accessing files is not supported with %1 archives", arcType)); return; } QString path = getPath(url, QUrl::StripTrailingSlash); QUrl newUrl = url; // but treat the archive itself as the archive root if (path == getPath(arcFile->url(), QUrl::StripTrailingSlash)) { newUrl.setPath(path + DIR_SEPARATOR); path = getPath(newUrl); } // we might be stating a real file if (QFileInfo(path).exists()) { QT_STATBUF buff; QT_STAT(path.toLocal8Bit(), &buff); QString mime; QMimeDatabase db; QMimeType result = db.mimeTypeForFile(path); if (result.isValid()) mime = result.name(); statEntry(KFileItem(QUrl::fromLocalFile(path), mime, buff.st_mode).entry()); finished(); return; } UDSEntry* entry = findFileEntry(newUrl); if (entry) { statEntry(*entry); finished(); } else error(KIO::ERR_DOES_NOT_EXIST, path); } void kio_krarcProtocol::copy(const QUrl &url, const QUrl &dest, int, KIO::JobFlags flags) { KRDEBUG("source: " << url.path() << " dest: " << dest.path()); if (!checkWriteSupport()) return; bool overwrite = !!(flags & KIO::Overwrite); // KDE HACK: opening the password dlg in copy causes error for the COPY, and further problems // that's why encrypted files are not allowed to copy if (!encrypted && dest.isLocalFile()) do { if (url.fileName() != dest.fileName()) break; if (QTextCodec::codecForLocale()->name() != codec->name()) break; //the file exists and we don't want to overwrite if ((!overwrite) && (QFile(getPath(dest)).exists())) { error((int)ERR_FILE_ALREADY_EXIST, QString(QFile::encodeName(getPath(dest)))); return; }; if (!setArcFile(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (newArchiveURL && !initDirDict(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } UDSEntry* entry = findFileEntry(url); if (copyCmd.isEmpty() || !entry) break; QString file = getPath(url).mid(getPath(arcFile->url()).length() + 1); QString destDir = getPath(dest, QUrl::StripTrailingSlash); if (!QDir(destDir).exists()) { int ndx = destDir.lastIndexOf(DIR_SEPARATOR_CHAR); if (ndx != -1) destDir.truncate(ndx + 1); } QDir::setCurrent(destDir); QString escapedFilename = file; if(arcType == "zip") { // left bracket needs to be escaped escapedFilename.replace('[', "[[]"); } KrLinecountingProcess proc; proc << copyCmd << getPath(arcFile->url(), QUrl::StripTrailingSlash) << escapedFilename; if (arcType == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! proc.setStandardInputFile("/dev/ptmx"); proc.setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect infoMessage(i18n("Unpacking %1...", url.fileName())); proc.start(); proc.waitForFinished(); if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) { error(KIO::ERR_CANNOT_WRITE, getPath(dest, QUrl::StripTrailingSlash) + "\n\n" + proc.getErrorMsg()); return; } if (!QFileInfo(getPath(dest, QUrl::StripTrailingSlash)).exists()) { error(KIO::ERR_CANNOT_WRITE, getPath(dest, QUrl::StripTrailingSlash)); return; } processedSize(KFileItem(*entry, url).size()); finished(); QDir::setCurrent(QDir::rootPath()); /* for being able to umount devices after copying*/ return; } while (0); if (encrypted) KRDEBUG("ERROR: " << url.path() << " is encrypted."); if (!dest.isLocalFile()) KRDEBUG("ERROR: " << url.path() << " is not a local file."); // CMD_COPY is no more in KF5 - replaced with 74 value (as stated in kio/src/core/commands_p.h, which could be found in cgit.kde.org/kio.git/tree) error(ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(mProtocol, 74)); } void kio_krarcProtocol::rename(const QUrl& src, const QUrl& dest, KIO::JobFlags flags) { Q_UNUSED(flags); KRDEBUG("renaming from: " << src.path() << " to: " << dest.path()); KRDEBUG("command: " << arcPath); if (!checkWriteSupport()) { return; } if (renCmd.isEmpty()) { error(KIO::ERR_CANNOT_RENAME, src.fileName()); return; } if (src.fileName() == dest.fileName()) { return; } KrLinecountingProcess proc; proc << renCmd << arcPath << src.path().remove(arcPath + '/') << dest.path().remove(arcPath + '/'); proc.start(); proc.waitForFinished(); if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) { error(KIO::ERR_CANNOT_RENAME, src.fileName()); return; } finished(); } void kio_krarcProtocol::listDir(const QUrl &url) { KRFUNC; KRDEBUG(getPath(url)); if (!setArcFile(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } if (listCmd.isEmpty()) { error(ERR_UNSUPPORTED_ACTION, i18n("Listing directories is not supported for %1 archives", arcType)); return; } QString path = getPath(url); if (path.right(1) != DIR_SEPARATOR) path = path + DIR_SEPARATOR; // it might be a real dir ! if (QFileInfo(path).exists()) { if (QFileInfo(path).isDir()) { QUrl redir; redir.setPath(getPath(url)); redirection(redir); finished(); } else { // maybe it's an archive ! error(ERR_IS_FILE, path); } return; } if (!initDirDict(url)) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } QString arcDir = path.mid(getPath(arcFile->url()).length()); arcDir.truncate(arcDir.lastIndexOf(DIR_SEPARATOR)); if (arcDir.right(1) != DIR_SEPARATOR) arcDir = arcDir + DIR_SEPARATOR; if (dirDict.find(arcDir) == dirDict.end()) { error(ERR_CANNOT_ENTER_DIRECTORY, getPath(url)); return; } UDSEntryList* dirList = dirDict[ arcDir ]; totalSize(dirList->size()); listEntries(*dirList); finished(); } bool kio_krarcProtocol::setArcFile(const QUrl &url) { KRFUNC; KRDEBUG(url.fileName()); QString path = getPath(url); time_t currTime = time(nullptr); archiveChanged = true; newArchiveURL = true; // is the file already set ? if (arcFile && getPath(arcFile->url(), QUrl::StripTrailingSlash) == path.left(getPath(arcFile->url(), QUrl::StripTrailingSlash).length())) { newArchiveURL = false; // Has it changed ? KFileItem* newArcFile = new KFileItem(arcFile->url(), QString(), arcFile->mode()); if (metaData("Charset") != currentCharset || !newArcFile->cmp(*arcFile)) { currentCharset = metaData("Charset"); codec = QTextCodec::codecForName(currentCharset.toLatin1()); if (codec == nullptr) codec = QTextCodec::codecForMib(4 /* latin-1 */); delete arcFile; password.clear(); extArcReady = false; arcFile = newArcFile; } else { // same old file delete newArcFile; archiveChanged = false; if (encrypted && password.isNull()) initArcParameters(); } } else { // it's a new file... extArcReady = false; // new archive file means new dirDict, too dirDict.clear(); if (arcFile) { delete arcFile; password.clear(); arcFile = nullptr; } QString newPath = path; if (newPath.right(1) != DIR_SEPARATOR) newPath = newPath + DIR_SEPARATOR; for (int pos = 0; pos >= 0; pos = newPath.indexOf(DIR_SEPARATOR, pos + 1)) { QFileInfo qfi(newPath.left(pos)); if (qfi.exists() && !qfi.isDir()) { QT_STATBUF stat_p; QT_LSTAT(newPath.left(pos).toLocal8Bit(), &stat_p); arcFile = new KFileItem(QUrl::fromLocalFile(newPath.left(pos)), QString(), stat_p.st_mode); break; } } if (!arcFile) { // KRDEBUG("ERROR: " << path << " does not exist."); error(ERR_DOES_NOT_EXIST, path); return false; // file not found } currentCharset = metaData("Charset"); codec = QTextCodec::codecForName(currentCharset.toLatin1()); if (codec == nullptr) codec = QTextCodec::codecForMib(4 /* latin-1 */); } /* FIX: file change can only be detected if the timestamp between the two consequent changes is more than 1s. If the archive is continuously changing (check: move files inside the archive), krarc may errorneusly think, that the archive file is unchanged, because the timestamp is the same as the previous one. This situation can only occur if the modification time equals with the current time. While this condition is true, we can say, that the archive is changing, so content reread is always necessary during that period. */ if (archiveChanging) archiveChanged = true; archiveChanging = (currTime == (time_t)arcFile->time(KFileItem::ModificationTime).toTime_t()); arcPath = getPath(arcFile->url(), QUrl::StripTrailingSlash); arcType = detectArchive(encrypted, arcPath); if (arcType == "tbz") arcType = "bzip2"; else if (arcType == "tgz") arcType = "gzip"; else if (arcType == "tlz") arcType = "lzma"; else if (arcType == "txz") arcType = "xz"; if (arcType.isEmpty()) { arcType = arcFile->mimetype(); arcType = getShortTypeFromMime(arcType); if (arcType == "jar") arcType = "zip"; } return initArcParameters(); } bool kio_krarcProtocol::initDirDict(const QUrl &url, bool forced) { KRFUNC; KRDEBUG(getPath(url)); // set the archive location //if( !setArcFile(getPath(url)) ) return false; // no need to rescan the archive if it's not changed // KRDEBUG("achiveChanged: " << archiveChanged << " forced: " << forced); if (!archiveChanged && !forced) { // KRDEBUG("doing nothing."); return true; } extArcReady = false; if (!setArcFile(url)) return false; /* if the archive was changed refresh the file information */ // write the temp file KrLinecountingProcess proc; QTemporaryFile temp; // parse the temp file if (!temp.open()) { error(ERR_CANNOT_READ, temp.fileName()); return false; } if (arcType != "bzip2" && arcType != "lzma" && arcType != "xz") { if (arcType == "rpm") { proc << listCmd << arcPath; proc.setStandardOutputFile(temp.fileName()); } else { proc << listCmd << getPath(arcFile->url(), QUrl::StripTrailingSlash); proc.setStandardOutputFile(temp.fileName()); } if (arcType == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! proc.setStandardInputFile("/dev/ptmx"); proc.setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect proc.start(); proc.waitForFinished(); if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(proc.exitCode())) return false; } // clear the dir dictionary QHashIterator< QString, KIO::UDSEntryList *> lit(dirDict); while (lit.hasNext()) delete lit.next().value(); dirDict.clear(); // add the "/" directory auto* root = new UDSEntryList(); dirDict.insert(DIR_SEPARATOR, root); // and the "/" UDSEntry UDSEntry entry; entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_NAME, "."); mode_t mode = parsePermString("drwxr-xr-x"); entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only root->append(entry); if (arcType == "bzip2" || arcType == "lzma" || arcType == "xz") abort(); char buf[1000]; QString line; int lineNo = 0; bool invalidLine = false; // the rar list is started with a ------ line. if (arcType == "rar" || arcType == "arj" || arcType == "lha" || arcType == "7z") { while (temp.readLine(buf, 1000) != -1) { line = decodeString(buf); if (line.startsWith(QLatin1String("----------"))) break; } } while (temp.readLine(buf, 1000) != -1) { line = decodeString(buf); if (arcType == "rar") { // the rar list is ended with a ------ line. if (line.startsWith(QLatin1String("----------"))) { invalidLine = !invalidLine; break; } if (invalidLine) continue; else { if (line[0] == '*') // encrypted archives starts with '*' line[0] = ' '; } } if (arcType == "ace") { // the ace list begins with a number. if (!line[0].isDigit()) continue; } if (arcType == "arj") { // the arj list is ended with a ------ line. if (line.startsWith(QLatin1String("----------"))) { invalidLine = !invalidLine; continue; } if (invalidLine) continue; else { temp.readLine(buf, 1000); line = line + decodeString(buf); temp.readLine(buf, 1000); line = line + decodeString(buf); temp.readLine(buf, 1000); line = line + decodeString(buf); } } if (arcType == "lha" || arcType == "7z") { // the arj list is ended with a ------ line. if (line.startsWith(QLatin1String("----------"))) break; } parseLine(lineNo++, line.trimmed()); } // close and delete our file temp.close(); archiveChanged = false; // KRDEBUG("done."); return true; } QString kio_krarcProtocol::findArcDirectory(const QUrl &url) { KRFUNC; KRDEBUG(url.fileName()); QString path = getPath(url); if (path.right(1) == DIR_SEPARATOR) path.truncate(path.length() - 1); if (!initDirDict(url)) { return QString(); } QString arcDir = path.mid(getPath(arcFile->url()).length()); arcDir.truncate(arcDir.lastIndexOf(DIR_SEPARATOR)); if (arcDir.right(1) != DIR_SEPARATOR) arcDir = arcDir + DIR_SEPARATOR; return arcDir; } UDSEntry* kio_krarcProtocol::findFileEntry(const QUrl &url) { KRFUNC; QString arcDir = findArcDirectory(url); if (arcDir.isEmpty()) return nullptr; QHash::iterator itef = dirDict.find(arcDir); if (itef == dirDict.end()) return nullptr; UDSEntryList* dirList = itef.value(); QString name = getPath(url); if (getPath(arcFile->url(), QUrl::StripTrailingSlash) == getPath(url, QUrl::StripTrailingSlash)) name = '.'; // the '/' case else { if (name.right(1) == DIR_SEPARATOR) name.truncate(name.length() - 1); name = name.mid(name.lastIndexOf(DIR_SEPARATOR) + 1); } UDSEntryList::iterator entry; for (entry = dirList->begin(); entry != dirList->end(); ++entry) { if ((entry->contains(KIO::UDSEntry::UDS_NAME)) && (entry->stringValue(KIO::UDSEntry::UDS_NAME) == name)) return &(*entry); } return nullptr; } QString kio_krarcProtocol::nextWord(QString &s, char d) { // Note: KRFUNC was not used here in order to avoid filling the log with too much information s = s.trimmed(); int j = s.indexOf(d, 0); QString temp = s.left(j); // find the leftmost word. s.remove(0, j); return temp; } mode_t kio_krarcProtocol::parsePermString(QString perm) { KRFUNC; mode_t mode = 0; // file type if (perm[0] == 'd') mode |= S_IFDIR; #ifndef Q_OS_WIN if (perm[0] == 'l') mode |= S_IFLNK; #endif if (perm[0] == '-') mode |= S_IFREG; // owner permissions if (perm[1] != '-') mode |= S_IRUSR; if (perm[2] != '-') mode |= S_IWUSR; if (perm[3] != '-') mode |= S_IXUSR; #ifndef Q_OS_WIN // group permissions if (perm[4] != '-') mode |= S_IRGRP; if (perm[5] != '-') mode |= S_IWGRP; if (perm[6] != '-') mode |= S_IXGRP; // other permissions if (perm[7] != '-') mode |= S_IROTH; if (perm[8] != '-') mode |= S_IWOTH; if (perm[9] != '-') mode |= S_IXOTH; #endif return mode; } UDSEntryList* kio_krarcProtocol::addNewDir(const QString& path) { KRFUNC; UDSEntryList* dir; // check if the current dir exists QHash::iterator itef = dirDict.find(path); if (itef != dirDict.end()) return itef.value(); // set dir to the parent dir dir = addNewDir(path.left(path.lastIndexOf(DIR_SEPARATOR, -2) + 1)); // add a new entry in the parent dir QString name = path.mid(path.lastIndexOf(DIR_SEPARATOR, -2) + 1); name = name.left(name.length() - 1); if (name == "." || name == "..") { // entries with these names wouldn't be displayed // don't translate since this is an internal error QString err = QString("Cannot handle path: ") + path; // KRDEBUG("ERROR: " << err); error(KIO::ERR_INTERNAL, err); exit(); } UDSEntry entry; entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_NAME, name); mode_t mode = parsePermString("drwxr-xr-x"); entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_SIZE, 0); entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_MODIFICATION_TIME, arcFile->time(KFileItem::ModificationTime).toTime_t()); dir->append(entry); // create a new directory entry and add it.. dir = new UDSEntryList(); dirDict.insert(path, dir); return dir; } void kio_krarcProtocol::parseLine(int lineNo, QString line) { KRFUNC; UDSEntryList* dir; UDSEntry entry; QString owner; QString group; QString symlinkDest; QString perm; mode_t mode = 0666; size_t size = 0; time_t time = ::time(nullptr); QString fullName; if (arcType == "zip") { // permissions perm = nextWord(line); // ignore the next 2 fields nextWord(line); nextWord(line); // size size = nextWord(line).toLong(); // ignore the next 2 fields nextWord(line);nextWord(line); // date & time QString d = nextWord(line); QDate qdate(d.mid(0, 4).toInt(), d.mid(4, 2).toInt(), d.mid(6, 2).toInt()); QTime qtime(d.mid(9, 2).toInt(), d.mid(11, 2).toInt(), d.mid(13, 2).toInt()); time = QDateTime(qdate, qtime).toTime_t(); // full name fullName = nextWord(line, '\n'); if (perm.length() != 10) perm = (perm.at(0) == 'd' || fullName.endsWith(DIR_SEPARATOR)) ? "drwxr-xr-x" : "-rw-r--r--" ; mode = parsePermString(perm); } if (arcType == "rar") { // permissions perm = nextWord(line); // size size = nextWord(line).toLong(); // ignore the next 2 fields : packed size and compression ration nextWord(line); nextWord(line); // date & time QString d = nextWord(line); int year = 1900 + d.mid(6, 2).toInt(); if (year < 1930) year += 100; QDate qdate(year, d.mid(3, 2).toInt(), d.mid(0, 2).toInt()); QString t = nextWord(line); QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0); time = QDateTime(qdate, qtime).toTime_t(); // checksum : ignored nextWord(line); // full name fullName = nextWord(line, '\n'); if (perm.length() == 7) { // windows rar permission format bool isDir = (perm.at(1).toLower() == 'd'); bool isReadOnly = (perm.at(2).toLower() == 'r'); perm = isDir ? "drwxr-xr-x" : "-rw-r--r--"; if (isReadOnly) perm[ 2 ] = '-'; } if (perm.length() != 10) perm = (perm.at(0) == 'd') ? "drwxr-xr-x" : "-rw-r--r--" ; mode = parsePermString(perm); } if (arcType == "arj") { nextWord(line); // full name fullName = nextWord(line, '\n'); // ignore the next 2 fields nextWord(line); nextWord(line); // size size = nextWord(line).toLong(); // ignore the next 2 fields nextWord(line); nextWord(line); // date & time QString d = nextWord(line); int year = 1900 + d.mid(0, 2).toInt(); if (year < 1930) year += 100; QDate qdate(year, d.mid(3, 2).toInt(), d.mid(6, 2).toInt()); QString t = nextWord(line); QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0); time = QDateTime(qdate, qtime).toTime_t(); // permissions perm = nextWord(line); if (perm.length() != 10) perm = (perm.at(0) == 'd') ? "drwxr-xr-x" : "-rw-r--r--" ; mode = parsePermString(perm); } if (arcType == "rpm") { // full name fullName = nextWord(line); // size size = nextWord(line).toULong(); // date & time time = nextWord(line).toULong(); // next field is md5sum, ignore it nextWord(line); // permissions mode = nextWord(line).toULong(nullptr, 8); // Owner & Group owner = nextWord(line); group = nextWord(line); // symlink destination #ifndef Q_OS_WIN if (S_ISLNK(mode)) { // ignore the next 3 fields nextWord(line); nextWord(line); nextWord(line); symlinkDest = nextWord(line); } #endif } if (arcType == "gzip") { if (!lineNo) return; //ignore the first line // first field is uncompressed size - ignore it nextWord(line); // size size = nextWord(line).toULong(); // ignore the next field nextWord(line); // full name fullName = nextWord(line); fullName = fullName.mid(fullName.lastIndexOf(DIR_SEPARATOR) + 1); } if (arcType == "lzma") { fullName = arcFile->name(); if (fullName.endsWith(QLatin1String("lzma"))) { fullName.truncate(fullName.length() - 5); } mode = arcFile->mode(); size = arcFile->size(); } if (arcType == "xz") { fullName = arcFile->name(); if (fullName.endsWith(QLatin1String("xz"))) { fullName.truncate(fullName.length() - 3); } mode = arcFile->mode(); size = arcFile->size(); } if (arcType == "bzip2") { // There is no way to list bzip2 files, so we take our information from // the archive itself... fullName = arcFile->name(); if (fullName.endsWith(QLatin1String("bz2"))) { fullName.truncate(fullName.length() - 4); } mode = arcFile->mode(); size = arcFile->size(); } if (arcType == "lha") { // permissions perm = nextWord(line); if (perm.length() != 10) perm = (perm.at(0) == 'd') ? "drwxr-xr-x" : "-rw-r--r--" ; mode = parsePermString(perm); // ignore the next field nextWord(line); // size size = nextWord(line).toLong(); // ignore the next field nextWord(line); // date & time int month = (QString("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec").split(',')).indexOf(nextWord(line)) + 1; int day = nextWord(line).toInt(); int year = QDate::currentDate().year(); QString third = nextWord(line); QTime qtime; if (third.contains(":")) qtime = QTime::fromString(third); else year = third.toInt(); QDate qdate(year, month, day); time = QDateTime(qdate, qtime).toTime_t(); // full name fullName = nextWord(line, '\n'); } if (arcType == "ace") { // date & time QString d = nextWord(line); int year = 1900 + d.mid(6, 2).toInt(); if (year < 1930) year += 100; QDate qdate(year, d.mid(3, 2).toInt(), d.mid(0, 2).toInt()); QString t = nextWord(line); QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0); time = QDateTime(qdate, qtime).toTime_t(); // ignore the next field nextWord(line); // size size = nextWord(line).toLong(); // ignore the next field nextWord(line); // full name fullName = nextWord(line, '\n'); if (fullName[ 0 ] == '*') // encrypted archives starts with '*' fullName = fullName.mid(1); } if (arcType == "deb") { // permissions perm = nextWord(line); mode = parsePermString(perm); // Owner & Group owner = nextWord(line, DIR_SEPARATOR_CHAR); group = nextWord(line).mid(1); // size size = nextWord(line).toLong(); // date & time QString d = nextWord(line); QDate qdate(d.mid(0, 4).toInt(), d.mid(5, 2).toInt(), d.mid(8, 2).toInt()); QString t = nextWord(line); QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), 0); time = QDateTime(qdate, qtime).toTime_t(); // full name fullName = nextWord(line, '\n').mid(1); //if ( fullName.right( 1 ) == "/" ) return; if (fullName.contains("->")) { symlinkDest = fullName.mid(fullName.indexOf("->") + 2); fullName = fullName.left(fullName.indexOf("->") - 1); } } if (arcType == "7z") { // date & time QString d = nextWord(line); QDate qdate(d.mid(0, 4).toInt(), d.mid(5, 2).toInt(), d.mid(8, 2).toInt()); QString t = nextWord(line); QTime qtime(t.mid(0, 2).toInt(), t.mid(3, 2).toInt(), t.mid(6, 2).toInt()); time = QDateTime(qdate, qtime).toTime_t(); // permissions perm = nextWord(line); bool isDir = (perm.at(0).toLower() == 'd'); bool isReadOnly = (perm.at(1).toLower() == 'r'); perm = isDir ? "drwxr-xr-x" : "-rw-r--r--"; if (isReadOnly) perm[ 2 ] = '-'; mode = parsePermString(perm); // size size = nextWord(line).toLong(); // ignore the next 15 characters line = line.mid(15); // full name fullName = nextWord(line, '\n'); } if (fullName.right(1) == DIR_SEPARATOR) fullName = fullName.left(fullName.length() - 1); if (!fullName.startsWith(DIR_SEPARATOR)) fullName = DIR_SEPARATOR + fullName; QString path = fullName.left(fullName.lastIndexOf(DIR_SEPARATOR) + 1); // set/create the directory UDSEntryList QHash::iterator itef = dirDict.find(path); if (itef == dirDict.end()) dir = addNewDir(path); else dir = itef.value(); QString name = fullName.mid(fullName.lastIndexOf(DIR_SEPARATOR) + 1); // file name entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_NAME, name); // file type entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only // file permissions entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only // file size entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_SIZE, size); // modification time entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_MODIFICATION_TIME, time); // link destination if (!symlinkDest.isEmpty()) { entry.UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_LINK_DEST, symlinkDest); } if (S_ISDIR(mode)) { fullName = fullName + DIR_SEPARATOR; if (dirDict.find(fullName) == dirDict.end()) dirDict.insert(fullName, new UDSEntryList()); else { // try to overwrite an existing entry UDSEntryList::iterator entryIt; for (entryIt = dir->begin(); entryIt != dir->end(); ++entryIt) { if (entryIt->contains(KIO::UDSEntry::UDS_NAME) && entryIt->stringValue(KIO::UDSEntry::UDS_NAME) == name) { entryIt->UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_MODIFICATION_TIME, time); entryIt->UDS_ENTRY_INSERT(KIO::UDSEntry::UDS_ACCESS, mode); return; } } return; // there is already an entry for this directory } } // multi volume archives can add a file twice, use only one UDSEntryList::iterator dirEntryIt; for (dirEntryIt = dir->begin(); dirEntryIt != dir->end(); ++dirEntryIt) if (dirEntryIt->contains(KIO::UDSEntry::UDS_NAME) && dirEntryIt->stringValue(KIO::UDSEntry::UDS_NAME) == name) return; dir->append(entry); } bool kio_krarcProtocol::initArcParameters() { KRFUNC; KRDEBUG("arcType: " << arcType); noencoding = false; cmd.clear(); listCmd = QStringList(); getCmd = QStringList(); copyCmd = QStringList(); delCmd = QStringList(); putCmd = QStringList(); renCmd = QStringList(); if (arcType == "zip") { noencoding = true; cmd = fullPathName("unzip"); listCmd << fullPathName("unzip") << "-ZTs-z-t-h"; getCmd << fullPathName("unzip") << "-p"; copyCmd << fullPathName("unzip") << "-jo"; if (QStandardPaths::findExecutable(QStringLiteral("zip")).isEmpty()) { delCmd = QStringList(); putCmd = QStringList(); } else { delCmd << fullPathName("zip") << "-d"; putCmd << fullPathName("zip") << "-ry"; } if (!QStandardPaths::findExecutable(QStringLiteral("7za")).isEmpty()) { renCmd << fullPathName("7za") << "rn"; } if (!getPassword().isEmpty()) { getCmd << "-P" << password; copyCmd << "-P" << password; putCmd << "-P" << password; } } else if (arcType == "rar") { noencoding = true; if (QStandardPaths::findExecutable(QStringLiteral("rar")).isEmpty()) { cmd = fullPathName("unrar"); listCmd << fullPathName("unrar") << "-c-" << "-v" << "v"; getCmd << fullPathName("unrar") << "p" << "-ierr" << "-idp" << "-c-" << "-y"; copyCmd << fullPathName("unrar") << "e" << "-y"; delCmd = QStringList(); putCmd = QStringList(); } else { cmd = fullPathName("rar"); listCmd << fullPathName("rar") << "-c-" << "-v" << "v"; getCmd << fullPathName("rar") << "p" << "-ierr" << "-idp" << "-c-" << "-y"; copyCmd << fullPathName("rar") << "e" << "-y"; delCmd << fullPathName("rar") << "d"; putCmd << fullPathName("rar") << "-r" << "a"; } if (!getPassword().isEmpty()) { getCmd << QString("-p%1").arg(password); listCmd << QString("-p%1").arg(password); copyCmd << QString("-p%1").arg(password); if (!putCmd.isEmpty()) { putCmd << QString("-p%1").arg(password); delCmd << QString("-p%1").arg(password); } } } else if (arcType == "rpm") { cmd = fullPathName("rpm"); listCmd << fullPathName("rpm") << "--dump" << "-lpq"; getCmd << fullPathName("cpio") << "--force-local" << "--no-absolute-filenames" << "-iuvdF"; delCmd = QStringList(); putCmd = QStringList(); copyCmd = QStringList(); } else if (arcType == "gzip") { cmd = fullPathName("gzip"); listCmd << fullPathName("gzip") << "-l"; getCmd << fullPathName("gzip") << "-dc"; copyCmd = QStringList(); delCmd = QStringList(); putCmd = QStringList(); } else if (arcType == "bzip2") { cmd = fullPathName("bzip2"); listCmd << fullPathName("bzip2"); getCmd << fullPathName("bzip2") << "-dc"; copyCmd = QStringList(); delCmd = QStringList(); putCmd = QStringList(); } else if (arcType == "lzma") { cmd = fullPathName("lzma"); listCmd << fullPathName("lzma"); getCmd << fullPathName("lzma") << "-dc"; copyCmd = QStringList(); delCmd = QStringList(); putCmd = QStringList(); } else if (arcType == "xz") { cmd = fullPathName("xz"); listCmd << fullPathName("xz"); getCmd << fullPathName("xz") << "-dc"; copyCmd = QStringList(); delCmd = QStringList(); putCmd = QStringList(); } else if (arcType == "arj") { cmd = fullPathName("arj"); listCmd << fullPathName("arj") << "v" << "-y" << "-v"; getCmd << fullPathName("arj") << "-jyov" << "-v" << "e"; copyCmd << fullPathName("arj") << "-jyov" << "-v" << "e"; delCmd << fullPathName("arj") << "d"; putCmd << fullPathName("arj") << "-r" << "a"; if (!getPassword().isEmpty()) { getCmd << QString("-g%1").arg(password); copyCmd << QString("-g%1").arg(password); putCmd << QString("-g%1").arg(password); } } else if (arcType == "lha") { cmd = fullPathName("lha"); listCmd << fullPathName("lha") << "l"; getCmd << fullPathName("lha") << "pq"; copyCmd << fullPathName("lha") << "eif"; delCmd << fullPathName("lha") << "d"; putCmd << fullPathName("lha") << "a"; } else if (arcType == "ace") { cmd = fullPathName("unace"); listCmd << fullPathName("unace") << "v"; getCmd << fullPathName("unace") << "e" << "-o"; copyCmd << fullPathName("unace") << "e" << "-o"; delCmd = QStringList(); putCmd = QStringList(); if (!getPassword().isEmpty()) { getCmd << QString("-p%1").arg(password); copyCmd << QString("-p%1").arg(password); } } else if (arcType == "deb") { cmd = fullPathName("dpkg"); listCmd << fullPathName("dpkg") << "-c"; getCmd << fullPathName("tar") << "xvf"; copyCmd = QStringList(); delCmd = QStringList(); putCmd = QStringList(); } else if (arcType == "7z") { noencoding = true; cmd = fullPathName("7z"); if (QStandardPaths::findExecutable(cmd).isEmpty()) cmd = fullPathName("7za"); listCmd << cmd << "l" << "-y"; getCmd << cmd << "e" << "-y"; copyCmd << cmd << "e" << "-y"; delCmd << cmd << "d" << "-y"; putCmd << cmd << "a" << "-y"; renCmd << cmd << "rn"; if (!getPassword().isEmpty()) { getCmd << QString("-p%1").arg(password); listCmd << QString("-p%1").arg(password); copyCmd << QString("-p%1").arg(password); if (!putCmd.isEmpty()) { putCmd << QString("-p%1").arg(password); delCmd << QString("-p%1").arg(password); } } } // checking if it's an absolute path #ifdef Q_OS_WIN if (cmd.length() > 2 && cmd[ 0 ].isLetter() && cmd[ 1 ] == ':') return true; #else if (cmd.startsWith(DIR_SEPARATOR)) return true; #endif if (QStandardPaths::findExecutable(cmd).isEmpty()) { error(KIO::ERR_CANNOT_LAUNCH_PROCESS, cmd + i18n("\nMake sure that the %1 binary is installed properly on your system.", cmd)); KRDEBUG("Failed to find cmd: " << cmd); return false; } return true; } bool kio_krarcProtocol::checkStatus(int exitCode) { KRFUNC; KRDEBUG(exitCode); return KrArcBaseManager::checkStatus(arcType, exitCode); } void kio_krarcProtocol::checkIf7zIsEncrypted(bool &encrypted, QString fileName) { KRFUNC; if (encryptedArchPath == fileName) encrypted = true; else { // we try to find whether the 7z archive is encrypted // this is hard as the headers are also compressed QString tester = fullPathName("7z"); if (QStandardPaths::findExecutable(tester).isEmpty()) { KRDEBUG("A 7z program was not found"); tester = fullPathName("7za"); if (QStandardPaths::findExecutable(tester).isEmpty()) { KRDEBUG("A 7za program was not found"); return; } } QString testCmd = tester + " t -y "; lastData = encryptedArchPath = ""; KrLinecountingProcess proc; proc << testCmd << fileName; connect(&proc, &KrLinecountingProcess::newOutputData, this, &kio_krarcProtocol::checkOutputForPassword); proc.start(); proc.waitForFinished(); encrypted = this->encrypted; if (encrypted) encryptedArchPath = fileName; } } void kio_krarcProtocol::checkOutputForPassword(KProcess * proc, QByteArray & buf) { KRFUNC; QString data = QString(buf); QString checkable = lastData + data; QStringList lines = checkable.split('\n'); lastData = lines[ lines.count() - 1 ]; for (int i = 0; i != lines.count(); i++) { QString line = lines[ i ].trimmed().toLower(); int ndx = line.indexOf("testing"); if (ndx >= 0) line.truncate(ndx); if (line.isEmpty()) continue; if (line.contains("password") && line.contains("enter")) { KRDEBUG("Encrypted 7z archive found!"); encrypted = true; proc->kill(); return; } } } void kio_krarcProtocol::invalidatePassword() { KRFUNC; KRDEBUG(getPath(arcFile->url(), QUrl::StripTrailingSlash) + DIR_SEPARATOR); if (!encrypted) return; KIO::AuthInfo authInfo; authInfo.caption = i18n("Krarc Password Dialog"); authInfo.username = "archive"; authInfo.readOnly = true; authInfo.keepPassword = true; authInfo.verifyPath = true; QString fileName = getPath(arcFile->url(), QUrl::StripTrailingSlash); authInfo.url = QUrl::fromLocalFile(ROOT_DIR); authInfo.url.setHost(fileName /*.replace('/','_')*/); authInfo.url.setScheme("krarc"); password.clear(); cacheAuthentication(authInfo); } QString kio_krarcProtocol::getPassword() { KRFUNC; KRDEBUG("Encrypted: " << encrypted); if (!password.isNull()) return password; if (!encrypted) return (password = ""); KIO::AuthInfo authInfo; authInfo.caption = i18n("Krarc Password Dialog"); authInfo.username = "archive"; authInfo.readOnly = true; authInfo.keepPassword = true; authInfo.verifyPath = true; QString fileName = getPath(arcFile->url(), QUrl::StripTrailingSlash); authInfo.url = QUrl::fromLocalFile(ROOT_DIR); authInfo.url.setHost(fileName /*.replace('/','_')*/); authInfo.url.setScheme("krarc"); if (checkCachedAuthentication(authInfo) && !authInfo.password.isNull()) { KRDEBUG(authInfo.password); return (password = authInfo.password); } authInfo.password.clear(); #if KIO_VERSION_MINOR >= 24 int errCode = openPasswordDialogV2(authInfo, i18n("Accessing the file requires a password.")); if (!errCode && !authInfo.password.isNull()) { #else if (openPasswordDialog(authInfo, i18n("Accessing the file requires a password.")) && !authInfo.password.isNull()) { #endif KRDEBUG(authInfo.password); return (password = authInfo.password); #if KIO_VERSION_MINOR >= 24 } else { error(errCode, QString()); #endif } KRDEBUG(password); return password; } QString kio_krarcProtocol::detectFullPathName(QString name) { // Note: KRFUNC was not used here in order to avoid filling the log with too much information KRDEBUG(name); name = name + EXEC_SUFFIX; QStringList path = QString::fromLocal8Bit(qgetenv("PATH")).split(':'); for (auto & it : path) { if (QDir(it).exists(name)) { QString dir = it; if (!dir.endsWith(DIR_SEPARATOR)) dir += DIR_SEPARATOR; return dir + name; } } return name; } QString kio_krarcProtocol::fullPathName(const QString& name) { // Note: KRFUNC was not used here in order to avoid filling the log with too much information KRDEBUG(name); QString supposedName = confGrp.readEntry(name, QString()); if (supposedName.isEmpty()) supposedName = detectFullPathName(name); return supposedName; } QString kio_krarcProtocol::localeEncodedString(QString str) { // Note: KRFUNC was not used here in order to avoid filling the log with too much information if (noencoding) return str; QByteArray array = codec->fromUnicode(str); // encoding the byte array to QString, mapping 0x0000-0x00FF to 0xE000-0xE0FF // see KrArcCodec for more explanation int size = array.size(); QString result; const char *data = array.data(); for (int i = 0; i != size; i++) { unsigned short ch = (((int)data[ i ]) & 0xFF) + 0xE000; // user defined character result.append(QChar(ch)); } return result; } QByteArray kio_krarcProtocol::encodeString(const QString& str) { // Note: KRFUNC was not used here in order to avoid filling the log with too much information if (noencoding) return QTextCodec::codecForLocale()->fromUnicode(str); return codec->fromUnicode(str); } QString kio_krarcProtocol::decodeString(char * buf) { // Note: KRFUNC was not used here in order to avoid filling the log with too much information if (noencoding) return QTextCodec::codecForLocale()->toUnicode(buf); return codec->toUnicode(buf); } QString kio_krarcProtocol::getPath(const QUrl &url, QUrl::FormattingOptions options) { // Note: KRFUNC was not used here in order to avoid filling the log with too much information QString path = url.adjusted(options).path(); REPLACE_DIR_SEP2(path); #ifdef Q_OS_WIN if (path.startsWith(DIR_SEPARATOR)) { int p = 1; while (p < path.length() && path[ p ] == DIR_SEPARATOR_CHAR) p++; /* /C:/Folder */ if (p + 2 <= path.length() && path[ p ].isLetter() && path[ p + 1 ] == ':') { path = path.mid(p); } } #endif return path; } #endif // KRARC_ENABLED diff --git a/krArc/krarc.h b/krArc/krarc.h index 403c917e..4c64fe1a 100644 --- a/krArc/krarc.h +++ b/krArc/krarc.h @@ -1,145 +1,145 @@ /***************************************************************************** * Copyright (C) 2003 Rafi Yanai * * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2004-2019 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 KRARC_H #define KRARC_H // QtCore #include #include #include #include #include #include #include #include #include #include "krarcbasemanager.h" #include "krlinecountingprocess.h" #include "../krusader/krdebuglogger.h" class KFileItem; class QByteArray; class QTextCodec; class kio_krarcProtocol : public QObject, public KIO::SlaveBase, public KrArcBaseManager { Q_OBJECT public: kio_krarcProtocol(const QByteArray &pool_socket, const QByteArray &app_socket); ~kio_krarcProtocol() override; - void stat(const QUrl &url) Q_DECL_OVERRIDE; - void get(const QUrl &url) Q_DECL_OVERRIDE; - void put(const QUrl &url, int permissions, KIO::JobFlags flags) Q_DECL_OVERRIDE; - void mkdir(const QUrl &url, int permissions) Q_DECL_OVERRIDE; - void listDir(const QUrl &url) Q_DECL_OVERRIDE; - void del(QUrl const & url, bool isFile) Q_DECL_OVERRIDE; - void copy(const QUrl &src, const QUrl &dest, int permissions, KIO::JobFlags flags) Q_DECL_OVERRIDE; - void rename(const QUrl &src, const QUrl & dest, KIO::JobFlags flags) Q_DECL_OVERRIDE; + void stat(const QUrl &url) override; + void get(const QUrl &url) override; + void put(const QUrl &url, int permissions, KIO::JobFlags flags) override; + void mkdir(const QUrl &url, int permissions) override; + void listDir(const QUrl &url) override; + void del(QUrl const & url, bool isFile) override; + void copy(const QUrl &src, const QUrl &dest, int permissions, KIO::JobFlags flags) override; + void rename(const QUrl &src, const QUrl & dest, KIO::JobFlags flags) override; public slots: void receivedData(KProcess *, QByteArray &); void checkOutputForPassword(KProcess *, QByteArray &); protected: virtual bool initDirDict(const QUrl &url, bool forced = false); virtual bool initArcParameters(); - void checkIf7zIsEncrypted(bool &, QString) Q_DECL_OVERRIDE; + void checkIf7zIsEncrypted(bool &, QString) override; virtual void parseLine(int lineNo, QString line); virtual bool setArcFile(const QUrl &url); virtual QString getPassword(); virtual void invalidatePassword(); QString getPath(const QUrl &url, QUrl::FormattingOptions options = nullptr); QString localeEncodedString(QString str); QByteArray encodeString(const QString&); QString decodeString(char *); // archive specific commands QString cmd; ///< the archiver name. QStringList listCmd; ///< list files. QStringList getCmd; ///< unpack files command. QStringList delCmd; ///< delete files command. QStringList putCmd; ///< add file command. QStringList copyCmd; ///< copy to file command. QStringList renCmd; ///< rename file command. private: void get(const QUrl &url, int tries); /** checks if a returned status ("exit code") of an archiving-related process is OK. */ bool checkStatus(int exitCode); /** service function for parseLine. */ QString nextWord(QString &s, char d = ' '); /** translate permission string to mode_t. */ mode_t parsePermString(QString perm); /** return the name of the directory inside the archive. */ QString findArcDirectory(const QUrl &url); /** find the UDSEntry of a file in a directory. */ KIO::UDSEntry* findFileEntry(const QUrl &url); /** add a new directory (file list container). */ KIO::UDSEntryList* addNewDir(const QString& path); QString fullPathName(const QString& name); static QString detectFullPathName(QString name); bool checkWriteSupport(); QHash dirDict; //< the directories data structure. bool encrypted; //< tells whether the archive is encrypted bool archiveChanged; //< true if the archive was changed. bool archiveChanging; //< true if the archive is currently changing. bool newArchiveURL; //< true if new archive was entered for the protocol bool noencoding; //< 7z files use UTF-16, so encoding is unnecessary KIO::filesize_t decompressedLen; //< the number of the decompressed bytes KFileItem* arcFile; //< the archive file item. QString arcPath; //< the archive location QString arcTempDir; //< the currently used temp directory. QString arcType; //< the archive type. bool extArcReady; //< Used for RPM & DEB files. QString password; //< Password for the archives KConfig krConf; //< The configuration file for krusader KConfigGroup confGrp; //< the 'Dependencies' config group QString lastData; QString encryptedArchPath; QString currentCharset; QTextCodec * codec; }; #ifdef Q_OS_WIN #define DIR_SEPARATOR "/" #define DIR_SEPARATOR2 "\\" #define DIR_SEPARATOR_CHAR '/' #define DIR_SEPARATOR_CHAR2 '\\' #define REPLACE_DIR_SEP2(x) x = x.replace( DIR_SEPARATOR2, DIR_SEPARATOR ); #define ROOT_DIR "C:\\" #define EXEC_SUFFIX ".exe" #else #define DIR_SEPARATOR "/" #define DIR_SEPARATOR2 "/" #define DIR_SEPARATOR_CHAR '/' #define DIR_SEPARATOR_CHAR2 '/' #define REPLACE_DIR_SEP2(x) #define ROOT_DIR "/" #define EXEC_SUFFIX "" #endif #endif diff --git a/krusader/ActionMan/addplaceholderpopup.h b/krusader/ActionMan/addplaceholderpopup.h index bf175a18..e576986d 100644 --- a/krusader/ActionMan/addplaceholderpopup.h +++ b/krusader/ActionMan/addplaceholderpopup.h @@ -1,348 +1,348 @@ /***************************************************************************** * Copyright (C) 2004 Shie Erlich * * Copyright (C) 2004 Rafi Yanai * * Copyright (C) 2004 Jonas Bähr * * Copyright (C) 2004-2019 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 ADDPLACEHOLDERPOPUP_H #define ADDPLACEHOLDERPOPUP_H // QtCore #include #include // QtWidgets #include #include #include "../UserAction/expander.h" class KLineEdit; class QToolButton; class QCheckBox; class KComboBox; class QSpinBox; /** * This reads Expander::placeholder[] and * fills a popup for easy access to the UserAction Placeholder */ class AddPlaceholderPopup : public QMenu { public: explicit AddPlaceholderPopup(QWidget *parent); /** * Use this to exec the popup. * @param pos Position where the popup should appear * @return the expression which can be placed in the UserAction commandline */ QString getPlaceholder(const QPoint& pos); protected: /** * This is called when a Placeholder got parameter. * @param currentPlaceholder A pointer to the Placeholder the user has chosen * @return a parameter-string */ QString getParameter(exp_placeholder* currentPlaceholder); private: QMenu *_activeSub, *_otherSub, *_leftSub, *_rightSub, *_independentSub; }; //////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////// Parameter Widgets /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// /** * abstract baseclass for all Parameter widgets */ class ParameterBase : public QWidget { public: inline ParameterBase(const exp_parameter& parameter, QWidget* parent) : QWidget(parent) { _necessary = parameter.necessary(); } /** * @return the text for the parameter */ virtual QString text() = 0; /** * @return the default of the parameter */ virtual QString preset() = 0; /** * re-init the parameter with the default */ virtual void reset() = 0; /** * @return true if the Parameter as a valid value */ virtual bool valid() = 0; /** * @return true if the Placeholder really needs this parameter */ inline bool necessary() { return _necessary; } private: bool _necessary; }; /** * The simple Parameter widgets: a line-edit with the description above * used by default */ class ParameterText : public ParameterBase { public: ParameterText(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KLineEdit * _lineEdit; QString _preset; }; /** * A line-edit with the "addPlaceholder"-button * used with default = "__placeholder" */ class ParameterPlaceholder : public ParameterBase { Q_OBJECT public: ParameterPlaceholder(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KLineEdit * _lineEdit; QToolButton* _button; private slots: void addPlaceholder(); }; /** * A Checkbox, default: checked; retuns "No" if unchecked * used with default = "__yes" */ class ParameterYes : public ParameterBase { public: ParameterYes(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: QCheckBox* _checkBox; }; /** * A Checkbox, default: unchecked; retuns "Yes" if checked * used with default = "__no" */ class ParameterNo : public ParameterBase { public: ParameterNo(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: QCheckBox* _checkBox; }; /** * A line-edit with the "file open"-button * used with default = "__file" */ class ParameterFile : public ParameterBase { Q_OBJECT public: ParameterFile(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KLineEdit * _lineEdit; QToolButton* _button; private slots: void addFile(); }; /** * A ComboBox with the description above * used with default = "__choose:item1;item2;..." */ class ParameterChoose : public ParameterBase { public: ParameterChoose(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KComboBox * _combobox; }; /** * An editable ComboBox with the predefined selections * used with default = "__select" */ class ParameterSelect : public ParameterBase { public: ParameterSelect(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KComboBox * _combobox; }; /** * A line-edit with a "choose dir"- and a bookmark-button * used with default = "__goto" */ class ParameterGoto : public ParameterBase { Q_OBJECT public: ParameterGoto(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KLineEdit * _lineEdit; QToolButton* _dirButton, *_placeholderButton; private slots: void setDir(); void addPlaceholder(); }; /** * A ComboBox with all profiles available for the Synchronizer * used with default = "__syncprofile" */ class ParameterSyncprofile : public ParameterBase { public: ParameterSyncprofile(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KComboBox * _combobox; }; /** * A ComboBox with all profiles available for the panels * used with default = "__panelprofile" */ class ParameterPanelprofile : public ParameterBase { public: ParameterPanelprofile(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KComboBox * _combobox; }; /** * A ComboBox with all profiles available for the Searchmodule * used with default = "__searchprofile" */ class ParameterSearch : public ParameterBase { public: ParameterSearch(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: KComboBox * _combobox; }; /** * A SpinBox for integer * used with default = "__int:min;max;step;value" */ class ParameterInt : public ParameterBase { public: ParameterInt(const exp_parameter& parameter, QWidget* parent); - QString text() Q_DECL_OVERRIDE; - QString preset() Q_DECL_OVERRIDE; - void reset() Q_DECL_OVERRIDE; - bool valid() Q_DECL_OVERRIDE; + QString text() override; + QString preset() override; + void reset() override; + bool valid() override; private: QSpinBox * _spinbox; int _default; }; //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////// ParameterDialog //////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// /** * Opens a dialog for the parameter. Depending on the default (preset) a different widget is used. * See Parameter-Classes for details */ class ParameterDialog : public QDialog { Q_OBJECT public: ParameterDialog(const exp_placeholder* currentPlaceholder, QWidget *parent); /** * Use this to execute the dialog. * @return a QString with all parameters; omitting the optional ones if they have the default-value. */ QString getParameter(); private: typedef QList ParameterList; ParameterList _parameter; int _parameterCount; private slots: void reset(); void slotOk(); }; #endif // ADDPLACEHOLDERPOPUP_H diff --git a/krusader/ActionMan/useractionlistview.h b/krusader/ActionMan/useractionlistview.h index c6eda59c..c8f939bb 100644 --- a/krusader/ActionMan/useractionlistview.h +++ b/krusader/ActionMan/useractionlistview.h @@ -1,87 +1,87 @@ /***************************************************************************** * Copyright (C) 2006 Jonas Bähr * * Copyright (C) 2006-2019 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 USERACTIONLISTVIEW_H #define USERACTIONLISTVIEW_H #include "../GUI/krtreewidget.h" class KrAction; class QString; class UserActionListViewItem; class QDomDocument; class UserActionListView : public KrTreeWidget { Q_OBJECT public: explicit UserActionListView(QWidget* parent = nullptr); ~UserActionListView() override; - QSize sizeHint() const Q_DECL_OVERRIDE; + QSize sizeHint() const override; void update(); void update(KrAction* action); UserActionListViewItem* insertAction(KrAction* action); KrAction* currentAction() const; void setCurrentAction(const KrAction*); QDomDocument dumpSelectedActions(QDomDocument* mergeDoc = nullptr) const; void removeSelectedActions(); /** * makes the first action in the list current */ void setFirstActionCurrent(); /** * makes @e item current and ensures its visibility */ protected slots: void slotCurrentItemChanged(QTreeWidgetItem*); protected: QTreeWidgetItem* findCategoryItem(const QString& category); UserActionListViewItem* findActionItem(const KrAction* action); }; class UserActionListViewItem : public QTreeWidgetItem { public: UserActionListViewItem(QTreeWidget* view, KrAction* action); UserActionListViewItem(QTreeWidgetItem* item, KrAction* action); ~UserActionListViewItem() override; void setAction(KrAction* action); KrAction* action() const; void update(); /** * This reimplements qt's compare-function in order to have categories on the top of the list */ - bool operator<(const QTreeWidgetItem &other) const Q_DECL_OVERRIDE; + bool operator<(const QTreeWidgetItem &other) const override; private: KrAction* _action; }; #endif diff --git a/krusader/Archive/abstractthreadedjob.cpp b/krusader/Archive/abstractthreadedjob.cpp index db6c4bcc..928a3b32 100644 --- a/krusader/Archive/abstractthreadedjob.cpp +++ b/krusader/Archive/abstractthreadedjob.cpp @@ -1,664 +1,664 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * Copyright (C) 2009-2019 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() : _maxProgressValue(0), _currentProgress(0), _exiting(false), _jobThread(nullptr) { } 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) { auto *event = dynamic_cast( e); switch (event->command()) { case CMD_SUCCESS: { emitResult(); } break; case CMD_ERROR: { auto 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: { auto maxValue = event->args()[ 0 ].value(); _maxProgressValue = maxValue; _currentProgress = 0; } break; case CMD_ADD_PROGRESS: { auto 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); auto *resultResp = new QList (); (*resultResp) << password; addEventResponse(resultResp); } break; case CMD_MESSAGE: { QString message = event->args()[ 0 ].value(); auto *ui = dynamic_cast(uiDelegate()); KMessageBox::information(ui ? ui->window() : nullptr, message); auto *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 nullptr; QList *resp = _stack.pop(); _locker.unlock(); return resp; } void AbstractThreadedJob::sendEvent(UserEvent * event) { QApplication::postEvent(this, event); } void AbstractThreadedJob::slotDownloadResult(KJob* job) { auto *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) {} ~AbstractJobObserver() override = default; - void processEvents() Q_DECL_OVERRIDE { + void processEvents() override { usleep(1000); qApp->processEvents(); } - void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE { + void subJobStarted(const QString & jobTitle, int count) override { _jobThread->sendReset(jobTitle); _jobThread->sendMaxProgressValue(count); } - void subJobStopped() Q_DECL_OVERRIDE { + void subJobStopped() override { } - bool wasCancelled() Q_DECL_OVERRIDE { + bool wasCancelled() override { return _jobThread->_exited; } - void error(const QString & error) Q_DECL_OVERRIDE { + void error(const QString & error) override { _jobThread->sendError(KIO::ERR_NO_CONTENT, error); } - void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE { + void detailedError(const QString & error, const QString & details) override { _jobThread->sendError(KIO::ERR_NO_CONTENT, error + '\n' + details); } - void incrementProgress(int c) Q_DECL_OVERRIDE { + void incrementProgress(int c) override { _jobThread->sendAddProgress(c, _jobThread->_progressTitle); } }; AbstractJobThread::AbstractJobThread() : _job(nullptr), _downloadTempDir(nullptr), _observer(nullptr), _tempFile(nullptr), _tempDir(nullptr), _exited(false) { } AbstractJobThread::~AbstractJobThread() { if (_downloadTempDir) { delete _downloadTempDir; _downloadTempDir = nullptr; } if (_observer) { delete _observer; _observer = nullptr; } if (_tempFile) { delete _tempFile; _tempFile = nullptr; } } void AbstractJobThread::run() { QTimer::singleShot(0, this, &AbstractJobThread::slotStart); QPointer threadLoop = new QEventLoop(this); _loop = threadLoop; threadLoop->exec(); _loop = nullptr; 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; auto * downloadEvent = new UserEvent(CMD_DOWNLOAD_FILES, args); QList * result = _job->getEventResponse(downloadEvent); if (result == nullptr) return QUrl(); auto 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; auto * errorEvent = new UserEvent(CMD_SUCCESS, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendError(int errorCode, const QString& message) { terminate(); QList args; args << errorCode; args << message; auto * errorEvent = new UserEvent(CMD_ERROR, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendInfo(const QString& message, const QString& a1, const QString& a2, const QString& a3, const QString& a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; auto * infoEvent = new UserEvent(CMD_INFO, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendReset(const QString& message, const QString& a1, const QString& a2, const QString& a3, const QString& a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; auto * infoEvent = new UserEvent(CMD_RESET, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendMaxProgressValue(qulonglong value) { QList args; args << value; auto * 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; auto * 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 != nullptr || _tempDir != nullptr) { sendInfo(i18n("Uploading to remote destination")); if (_tempFile) { QList urlList; urlList << QUrl::fromLocalFile(_tempFileName); QList args; args << KrServices::toStringList(urlList); args << _tempFileTarget; auto * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == nullptr) return false; auto 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; auto * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == nullptr) return false; auto 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; auto * getPasswdEvent = new UserEvent(CMD_GET_PASSWORD, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == nullptr) 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; auto * getPasswdEvent = new UserEvent(CMD_MESSAGE, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == nullptr) 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/Archive/abstractthreadedjob.h b/krusader/Archive/abstractthreadedjob.h index b14a986a..1a314726 100644 --- a/krusader/Archive/abstractthreadedjob.h +++ b/krusader/Archive/abstractthreadedjob.h @@ -1,188 +1,188 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * Copyright (C) 2009-2019 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 ABSTRACTTHREADEDJOB_H #define ABSTRACTTHREADEDJOB_H // QtCore #include #include #include #include #include #include #include #include #include #include #include #include class AbstractJobThread; class QTemporaryDir; class UserEvent; class KRarcObserver; class QTemporaryFile; class AbstractThreadedJob : public KIO::Job { friend class AbstractJobThread; Q_OBJECT protected: AbstractThreadedJob(); void addEventResponse(QList * obj); QList * getEventResponse(UserEvent * event); void sendEvent(UserEvent * event); virtual ~AbstractThreadedJob(); - virtual bool event(QEvent *) Q_DECL_OVERRIDE; + virtual bool event(QEvent *) override; virtual void startAbstractJobThread(AbstractJobThread*); - virtual bool doSuspend() Q_DECL_OVERRIDE { + virtual bool doSuspend() override { return false; } protected slots: void slotDownloadResult(KJob*); void slotProcessedAmount(KJob *, KJob::Unit, qulonglong); void slotTotalAmount(KJob *, KJob::Unit, qulonglong); void slotSpeed(KJob *, unsigned long); void slotDescription(KJob *job, const QString &title, const QPair &field1, const QPair &field2); public: QMutex _locker; QWaitCondition _waiter; QStack *> _stack; QString _title; qulonglong _maxProgressValue; qulonglong _currentProgress; QTime _time; bool _exiting; private: AbstractJobThread * _jobThread; }; class AbstractJobThread : public QThread { friend class AbstractThreadedJob; friend class AbstractJobObserver; Q_OBJECT public: AbstractJobThread(); virtual ~AbstractJobThread(); void abort(); KRarcObserver * observer(); protected slots: virtual void slotStart() = 0; protected: - virtual void run() Q_DECL_OVERRIDE; + virtual void run() override; void setJob(AbstractThreadedJob * job) { _job = job; } QList remoteUrls(const QUrl &baseUrl, const QStringList & files); QUrl downloadIfRemote(const QUrl &baseUrl, const QStringList & files); void countLocalFiles(const QUrl &baseUrl, const QStringList &names, unsigned long &totalFiles); void sendError(int errorCode, const QString& message); void sendInfo(const QString& message, const QString& a1 = QString(), const QString& a2 = QString(), const QString& a3 = QString(), const QString& a4 = QString()); void sendReset(const QString& message, const QString& a1 = QString(""), const QString& a2 = QString(""), const QString& a3 = QString(""), const QString& a4 = QString("")); void sendSuccess(); void sendMessage(const QString &message); void sendMaxProgressValue(qulonglong value); void sendAddProgress(qulonglong value, const QString &progress = QString()); void setProgressTitle(const QString &title) { _progressTitle = title; } QString tempFileIfRemote(const QUrl &kurl, const QString &type); QString tempDirIfRemote(const QUrl &kurl); bool uploadTempFiles(); bool isExited() { return _exited; } void terminate(); QString getPassword(const QString &path); bool getArchiveInformation(QString &, QString &, QString &, QString &, const QUrl &); AbstractThreadedJob *_job; QEventLoop *_loop; QTemporaryDir *_downloadTempDir; KRarcObserver *_observer; QTemporaryFile *_tempFile; QString _tempFileName; QUrl _tempFileTarget; QTemporaryDir *_tempDir; QString _tempDirName; QUrl _tempDirTarget; bool _exited; QString _progressTitle; }; enum PossibleCommands { CMD_ERROR = 1, CMD_INFO = 2, CMD_RESET = 3, CMD_DOWNLOAD_FILES = 4, CMD_UPLOAD_FILES = 5, CMD_SUCCESS = 6, CMD_MAXPROGRESSVALUE = 7, CMD_ADD_PROGRESS = 8, CMD_GET_PASSWORD = 9, CMD_MESSAGE = 10 }; class UserEvent : public QEvent { public: UserEvent(int command, const QList &args) : QEvent(QEvent::User), _command(command), _args(args) {} inline int command() { return _command; } inline const QList & args() { return _args; } protected: int _command; QList _args; }; #endif // __ABSTRACTTHREADED_JOB_H__ diff --git a/krusader/Archive/kr7zencryptionchecker.h b/krusader/Archive/kr7zencryptionchecker.h index 0c7ea9d3..c6df781c 100644 --- a/krusader/Archive/kr7zencryptionchecker.h +++ b/krusader/Archive/kr7zencryptionchecker.h @@ -1,53 +1,53 @@ /***************************************************************************** * Copyright (C) 2001 Shie Erlich * * Copyright (C) 2001 Rafi Yanai * * Copyright (C) 2004-2019 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 KR7ZENCRYPTIONCHECKER_H #define KR7ZENCRYPTIONCHECKER_H #include // for setsid, see Kr7zEncryptionChecker::setupChildProcess #include // for kill #include /** * Used by ArcHandler. */ class Kr7zEncryptionChecker : public KProcess { Q_OBJECT public: Kr7zEncryptionChecker(); protected: - void setupChildProcess() Q_DECL_OVERRIDE; + void setupChildProcess() override; public slots: void receivedOutput(); bool isEncrypted(); private: QString fileName; bool encrypted; QString lastData; }; #endif // KR7ZENCRYPTIONCHECKER_H diff --git a/krusader/Archive/krarchandler.cpp b/krusader/Archive/krarchandler.cpp index 6cbeabc9..6200d749 100644 --- a/krusader/Archive/krarchandler.cpp +++ b/krusader/Archive/krarchandler.cpp @@ -1,669 +1,669 @@ /***************************************************************************** * Copyright (C) 2001 Shie Erlich * * Copyright (C) 2001 Rafi Yanai * * Copyright (C) 2004-2019 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 "krarchandler.h" // QtCore #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include "kr7zencryptionchecker.h" #include "../krglobal.h" #include "../defaults.h" #include "../krservices.h" #include "../Dialogs/krpleasewait.h" #include "../../krArc/krlinecountingprocess.h" #if 0 class DefaultKRarcObserver : public KRarcObserver { public: DefaultKRarcObserver() {} virtual ~DefaultKRarcObserver() {} - virtual void processEvents() Q_DECL_OVERRIDE { + virtual void processEvents() override { usleep(1000); qApp->processEvents(); } - virtual void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE { + virtual void subJobStarted(const QString & jobTitle, int count) override { krApp->startWaiting(jobTitle, count, true); } - virtual void subJobStopped() Q_DECL_OVERRIDE { + virtual void subJobStopped() override { krApp->stopWait(); } - virtual bool wasCancelled() Q_DECL_OVERRIDE { + virtual bool wasCancelled() override { return krApp->wasWaitingCancelled(); } - virtual void error(const QString & error) Q_DECL_OVERRIDE { + virtual void error(const QString & error) override { KMessageBox::error(krApp, error, i18n("Error")); } - virtual void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE { + virtual void detailedError(const QString & error, const QString & details) override { KMessageBox::detailedError(krApp, error, details, i18n("Error")); } - virtual void incrementProgress(int c) Q_DECL_OVERRIDE { + virtual void incrementProgress(int c) override { krApp->plzWait->incProgress(c); } }; #endif static QStringList arcProtocols = QString("tar;bzip;bzip2;lzma;xz;gzip;krarc;zip").split(';'); KWallet::Wallet * KRarcHandler::wallet = nullptr; QStringList KRarcHandler::supportedPackers() { QStringList packers; // we will simply try to find the packers here.. if (KrServices::cmdExist("tar")) packers.append("tar"); if (KrServices::cmdExist("gzip")) packers.append("gzip"); if (KrServices::cmdExist("bzip2")) packers.append("bzip2"); if (KrServices::cmdExist("lzma")) packers.append("lzma"); if (KrServices::cmdExist("xz")) packers.append("xz"); if (KrServices::cmdExist("unzip")) packers.append("unzip"); if (KrServices::cmdExist("zip")) packers.append("zip"); if (KrServices::cmdExist("zip")) packers.append("cbz"); if (KrServices::cmdExist("lha")) packers.append("lha"); if (KrServices::cmdExist("cpio")) packers.append("cpio"); if (KrServices::cmdExist("unrar")) packers.append("unrar"); if (KrServices::cmdExist("rar")) packers.append("rar"); if (KrServices::cmdExist("rar")) packers.append("cbr"); if (KrServices::cmdExist("arj")) packers.append("arj"); if (KrServices::cmdExist("unarj")) packers.append("unarj"); if (KrServices::cmdExist("unace")) packers.append("unace"); if (KrServices::cmdExist("dpkg")) packers.append("dpkg"); if (KrServices::cmdExist("7z") || KrServices::cmdExist("7za")) packers.append("7z"); if (KrServices::cmdExist("rpm") && KrServices::cmdExist("rpm2cpio")) packers.append("rpm"); // qDebug() << "Supported Packers:"; //QStringList::Iterator it; //for( it = packers.begin(); it != packers.end(); ++it ) // qDebug() << *it; return packers; } bool KRarcHandler::arcSupported(QString type) { // lst will contain the supported unpacker list... const KConfigGroup group(krConfig, "Archives"); const QStringList lst = group.readEntry("Supported Packers", QStringList()); // Let's notice that in some cases the QString `type` that arrives here // represents a mimetype, and in some other cases it represents // a short identifier. // If `type` is not a short identifier then it's supposed that `type` is a mime type if (type.length() > maxLenType) { type = getShortTypeFromMime(type); } return (type == "zip" && lst.contains("unzip")) || (type == "tar" && lst.contains("tar")) || (type == "tbz" && lst.contains("tar")) || (type == "tgz" && lst.contains("tar")) || (type == "tlz" && lst.contains("tar")) || (type == "txz" && lst.contains("tar")) || (type == "tarz" && lst.contains("tar")) || (type == "gzip" && lst.contains("gzip")) || (type == "bzip2" && lst.contains("bzip2")) || (type == "lzma" && lst.contains("lzma")) || (type == "xz" && lst.contains("xz")) || (type == "lha" && lst.contains("lha")) || (type == "ace" && lst.contains("unace")) || (type == "rpm" && lst.contains("cpio")) || (type == "cpio" && lst.contains("cpio")) || (type == "rar" && (lst.contains("unrar") || lst.contains("rar"))) || (type == "arj" && (lst.contains("unarj") || lst.contains("arj"))) || (type == "deb" && (lst.contains("dpkg") && lst.contains("tar"))) || (type == "7z" && lst.contains("7z")); } long KRarcHandler::arcFileCount(const QString& archive, const QString& type, const QString& password, KRarcObserver *observer) { int divideWith = 1; // first check if supported if (!arcSupported(type)) return 0; // bzip2, gzip, etc. archives contain only one file if (type == "bzip2" || type == "gzip" || type == "lzma" || type == "xz") return 1L; // set the right lister to do the job QStringList lister; if (type == "zip") lister << KrServices::fullPathName("unzip") << "-ZTs"; else if (type == "tar") lister << KrServices::fullPathName("tar") << "-tvf"; else if (type == "tgz") lister << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tarz") lister << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tbz") lister << KrServices::fullPathName("tar") << "-tjvf"; else if (type == "tlz") lister << KrServices::fullPathName("tar") << "--lzma" << "-tvf"; else if (type == "txz") lister << KrServices::fullPathName("tar") << "--xz" << "-tvf"; else if (type == "lha") lister << KrServices::fullPathName("lha") << "l"; else if (type == "rar") lister << KrServices::fullPathName(KrServices::cmdExist("rar") ? "rar" : "unrar") << "l" << "-v"; else if (type == "ace") lister << KrServices::fullPathName("unace") << "l"; else if (type == "arj") { if (KrServices::cmdExist("arj")) lister << KrServices::fullPathName("arj") << "v" << "-y" << "-v", divideWith = 4; else lister << KrServices::fullPathName("unarj") << "l"; } else if (type == "rpm") lister << KrServices::fullPathName("rpm") << "--dump" << "-lpq"; else if (type == "deb") lister << KrServices::fullPathName("dpkg") << "-c"; else if (type == "7z") lister << KrServices::fullPathName("7z") << "-y" << "l"; else return 0L; if (!password.isNull()) { if (type == "arj") lister << QString("-g%1").arg(password); if (type == "ace" || type == "rar" || type == "7z") lister << QString("-p%1").arg(password); } // tell the user to wait observer->subJobStarted(i18n("Counting files in archive"), 0); // count the number of files in the archive long count = 1; KProcess list; list << lister << archive; if (type == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! list.setStandardInputFile("/dev/ptmx"); list.setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect list.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (list.waitForStarted()) while (list.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) list.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); if (list.exitStatus() != QProcess::NormalExit || !checkStatus(type, list.exitCode())) { observer->detailedError(i18n("Failed to list the content of the archive (%1).", archive), QString::fromLocal8Bit(list.readAllStandardError())); return 0; } count = list.readAllStandardOutput().count('\n'); //make sure you call stopWait after this function return... // observer->subJobStopped(); return count / divideWith; } bool KRarcHandler::unpack(QString archive, const QString& type, const QString& password, const QString& dest, KRarcObserver *observer) { KConfigGroup group(krConfig, "Archives"); if (group.readEntry("Test Before Unpack", _TestBeforeUnpack)) { // test first - or be sorry later... if (type != "rpm" && type != "deb" && !test(archive, type, password, observer, 0)) { observer->error(i18n("Failed to unpack %1.", archive)); return false; } } // count the files in the archive long count = arcFileCount(archive, type, password, observer); if (count == 0) return false; // not supported if (count == 1) count = 0; // choose the right packer for the job QString cpioName; QStringList packer; // set the right packer to do the job if (type == "zip") packer << KrServices::fullPathName("unzip") << "-o"; else if (type == "tar") packer << KrServices::fullPathName("tar") << "-xvf"; else if (type == "tgz") packer << KrServices::fullPathName("tar") << "-xvzf"; else if (type == "tarz") packer << KrServices::fullPathName("tar") << "-xvzf"; else if (type == "tbz") packer << KrServices::fullPathName("tar") << "-xjvf"; else if (type == "tlz") packer << KrServices::fullPathName("tar") << "--lzma" << "-xvf"; else if (type == "txz") packer << KrServices::fullPathName("tar") << "--xz" << "-xvf"; else if (type == "gzip") packer << KrServices::fullPathName("gzip") << "-cd"; else if (type == "bzip2") packer << KrServices::fullPathName("bzip2") << "-cdk"; else if (type == "lzma") packer << KrServices::fullPathName("lzma") << "-cdk"; else if (type == "xz") packer << KrServices::fullPathName("xz") << "-cdk"; else if (type == "lha") packer << KrServices::fullPathName("lha") << "xf"; else if (type == "rar") packer << KrServices::fullPathName(KrServices::cmdExist("rar") ? "rar" : "unrar") << "-y" << "x"; else if (type == "ace") packer << KrServices::fullPathName("unace") << "x"; else if (type == "arj") { if (KrServices::cmdExist("arj")) packer << KrServices::fullPathName("arj") << "-y" << "-v" << "x"; else packer << KrServices::fullPathName("unarj") << "x"; } else if (type == "7z") packer << KrServices::fullPathName("7z") << "-y" << "x"; else if (type == "rpm") { // TODO use QTemporaryFile (setAutoRemove(false) when asynchrone) cpioName = QDir::tempPath() + QStringLiteral("/contents.cpio"); KrLinecountingProcess cpio; cpio << KrServices::fullPathName("rpm2cpio") << archive; cpio.setStandardOutputFile(cpioName); // TODO maybe no tmpfile but a pipe (setStandardOutputProcess(packer)) cpio.start(); if (!cpio.waitForFinished() || cpio.exitStatus() != QProcess::NormalExit || !checkStatus("cpio", cpio.exitCode())) { observer->detailedError(i18n("Failed to convert rpm (%1) to cpio.", archive), cpio.getErrorMsg()); return 0; } archive = cpioName; packer << KrServices::fullPathName("cpio") << "--force-local" << "--no-absolute-filenames" << "-iuvdF"; } else if (type == "deb") { // TODO use QTemporaryFile (setAutoRemove(false) when asynchrone) cpioName = QDir::tempPath() + QStringLiteral("/contents.tar"); KrLinecountingProcess dpkg; dpkg << KrServices::fullPathName("dpkg") << "--fsys-tarfile" << archive; dpkg.setStandardOutputFile(cpioName); // TODO maybe no tmpfile but a pipe (setStandardOutputProcess(packer)) dpkg.start(); if (!dpkg.waitForFinished() || dpkg.exitStatus() != QProcess::NormalExit || !checkStatus("deb", dpkg.exitCode())) { observer->detailedError(i18n("Failed to convert deb (%1) to tar.", archive), dpkg.getErrorMsg()); return 0; } archive = cpioName; packer << KrServices::fullPathName("tar") << "xvf"; } else return false; if (!password.isNull()) { if (type == "zip") packer << "-P" << password; if (type == "arj") packer << QString("-g%1").arg(password); if (type == "ace" || type == "rar" || type == "7z") packer << QString("-p%1").arg(password); } // unpack the files KrLinecountingProcess proc; proc << packer << archive; if (type == "bzip2" || type == "gzip" || type == "lzma" || type == "xz") { QString arcname = archive.mid(archive.lastIndexOf("/") + 1); if (arcname.contains(".")) arcname = arcname.left(arcname.lastIndexOf(".")); proc.setStandardOutputFile(dest + '/' + arcname); } if (type == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! proc.setStandardInputFile("/dev/ptmx"); proc.setWorkingDirectory(dest); // tell the user to wait observer->subJobStarted(i18n("Unpacking File(s)"), count); if (count != 0) { connect(&proc, &KrLinecountingProcess::newOutputLines, observer, &KRarcObserver::incrementProgress); if (type == "rpm") connect(&proc, &KrLinecountingProcess::newErrorLines, observer, &KRarcObserver::incrementProgress); } // start the unpacking process proc.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (proc.waitForStarted()) while (proc.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) proc.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); if (!cpioName.isEmpty()) QFile(cpioName).remove(); /* remove the cpio file */ // check the return value if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(type, proc.exitCode())) { observer->detailedError(i18n("Failed to unpack %1.", archive), observer->wasCancelled() ? i18n("User cancelled.") : proc.getErrorMsg()); return false; } return true; // SUCCESS } bool KRarcHandler::test(const QString& archive, const QString& type, const QString& password, KRarcObserver *observer, long count) { // choose the right packer for the job QStringList packer; // set the right packer to do the job if (type == "zip") packer << KrServices::fullPathName("unzip") << "-t"; else if (type == "tar") packer << KrServices::fullPathName("tar") << "-tvf"; else if (type == "tgz") packer << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tarz") packer << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tbz") packer << KrServices::fullPathName("tar") << "-tjvf"; else if (type == "tlz") packer << KrServices::fullPathName("tar") << "--lzma" << "-tvf"; else if (type == "txz") packer << KrServices::fullPathName("tar") << "--xz" << "-tvf"; else if (type == "gzip") packer << KrServices::fullPathName("gzip") << "-tv"; else if (type == "bzip2") packer << KrServices::fullPathName("bzip2") << "-tv"; else if (type == "lzma") packer << KrServices::fullPathName("lzma") << "-tv"; else if (type == "xz") packer << KrServices::fullPathName("xz") << "-tv"; else if (type == "rar") packer << KrServices::fullPathName(KrServices::cmdExist("rar") ? "rar" : "unrar") << "t"; else if (type == "ace") packer << KrServices::fullPathName("unace") << "t"; else if (type == "lha") packer << KrServices::fullPathName("lha") << "t"; else if (type == "arj") packer << KrServices::fullPathName(KrServices::cmdExist("arj") ? "arj" : "unarj") << "t"; else if (type == "cpio") packer << KrServices::fullPathName("cpio") << "--only-verify-crc" << "-tvF"; else if (type == "7z") packer << KrServices::fullPathName("7z") << "-y" << "t"; else return false; if (!password.isNull()) { if (type == "zip") packer << "-P" << password; if (type == "arj") packer << QString("-g%1").arg(password); if (type == "ace" || type == "rar" || type == "7z") packer << QString("-p%1").arg(password); } // unpack the files KrLinecountingProcess proc; proc << packer << archive; if (type == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! proc.setStandardInputFile("/dev/ptmx"); // tell the user to wait observer->subJobStarted(i18n("Testing Archive"), count); if (count != 0) connect(&proc, &KrLinecountingProcess::newOutputLines, observer, &KRarcObserver::incrementProgress); // start the unpacking process proc.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (proc.waitForStarted()) while (proc.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) proc.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); // check the return value if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(type, proc.exitCode())) return false; return true; // SUCCESS } bool KRarcHandler::pack(QStringList fileNames, QString type, const QString& dest, long count, QMap extraProps, KRarcObserver *observer) { // set the right packer to do the job QStringList packer; if (type == "zip") { packer << KrServices::fullPathName("zip") << "-ry"; } else if (type == "cbz") { packer << KrServices::fullPathName("zip") << "-ry"; type = "zip"; } else if (type == "tar") { packer << KrServices::fullPathName("tar") << "-cvf"; } else if (type == "tar.gz") { packer << KrServices::fullPathName("tar") << "-cvzf"; type = "tgz"; } else if (type == "tar.bz2") { packer << KrServices::fullPathName("tar") << "-cvjf"; type = "tbz"; } else if (type == "tar.lzma") { packer << KrServices::fullPathName("tar") << "--lzma" << "-cvf"; type = "tlz"; } else if (type == "tar.xz") { packer << KrServices::fullPathName("tar") << "--xz" << "-cvf"; type = "txz"; } else if (type == "rar") { packer << KrServices::fullPathName("rar") << "-r" << "a"; } else if (type == "cbr") { packer << KrServices::fullPathName("rar") << "-r" << "a"; type = "rar"; } else if (type == "lha") { packer << KrServices::fullPathName("lha") << "a"; } else if (type == "arj") { packer << KrServices::fullPathName("arj") << "-r" << "-y" << "a"; } else if (type == "7z") { packer << KrServices::fullPathName("7z") << "-y" << "a"; } else return false; QString password; if (extraProps.count("Password") > 0) { password = extraProps[ "Password" ]; if (!password.isNull()) { if (type == "zip") packer << "-P" << password; else if (type == "arj") packer << QString("-g%1").arg(password); else if (type == "ace" || type == "7z") packer << QString("-p%1").arg(password); else if (type == "rar") { if (extraProps.count("EncryptHeaders") > 0) packer << QString("-hp%1").arg(password); else packer << QString("-p%1").arg(password); } else password.clear(); } } if (extraProps.count("VolumeSize") > 0) { QString sizeStr = extraProps[ "VolumeSize" ]; KIO::filesize_t size = sizeStr.toLongLong(); if (size >= 10000) { if (type == "arj" || type == "rar") packer << QString("-v%1b").arg(sizeStr); } } if (extraProps.count("CompressionLevel") > 0) { int level = extraProps[ "CompressionLevel" ].toInt() - 1; if (level < 0) level = 0; if (level > 8) level = 8; if (type == "rar") { static const int rarLevels[] = { 0, 1, 2, 2, 3, 3, 4, 4, 5 }; packer << QString("-m%1").arg(rarLevels[ level ]); } else if (type == "arj") { static const int arjLevels[] = { 0, 4, 4, 3, 3, 2, 2, 1, 1 }; packer << QString("-m%1").arg(arjLevels[ level ]); } else if (type == "zip") { static const int zipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 }; packer << QString("-%1").arg(zipLevels[ level ]); } else if (type == "7z") { static const int sevenZipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 }; packer << QString("-mx%1").arg(sevenZipLevels[ level ]); } } if (extraProps.count("CommandLineSwitches") > 0) packer << QString("%1").arg(extraProps[ "CommandLineSwitches" ]); // prepare to pack KrLinecountingProcess proc; proc << packer << dest; for (auto & fileName : fileNames) { proc << fileName; } // tell the user to wait observer->subJobStarted(i18n("Packing File(s)"), count); if (count != 0) connect(&proc, &KrLinecountingProcess::newOutputLines, observer, &KRarcObserver::incrementProgress); // start the packing process proc.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (proc.waitForStarted()) while (proc.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) proc.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); // check the return value if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(type, proc.exitCode())) { observer->detailedError(i18n("Failed to pack %1.", dest), observer->wasCancelled() ? i18n("User cancelled.") : proc.getErrorMsg()); return false; } KConfigGroup group(krConfig, "Archives"); if (group.readEntry("Test Archives", _TestArchives) && !test(dest, type, password, observer, count)) { observer->error(i18n("Failed to pack %1.", dest)); return false; } return true; // SUCCESS } bool KRarcHandler::openWallet() { if (!wallet) { // find a suitable parent window QWidget *actWindow = QApplication::activeWindow(); if (!actWindow) actWindow = (QWidget*) QApplication::desktop(); wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), actWindow->effectiveWinId()); } return (wallet != nullptr); } QString KRarcHandler::getPassword(const QString& path) { QString password; QString key = "krarc-" + path; if (!KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::PasswordFolder(), key)) { if (!KWallet::Wallet::isOpen(KWallet::Wallet::NetworkWallet()) && wallet != nullptr) { delete wallet; wallet = nullptr; } if (openWallet() && wallet->hasFolder(KWallet::Wallet::PasswordFolder())) { wallet->setFolder(KWallet::Wallet::PasswordFolder()); QMap map; if (wallet->readMap(key, map) == 0) { QMap::const_iterator it = map.constFind("password"); if (it != map.constEnd()) password = it.value(); } } } bool keep = true; QString user = "archive"; QPointer passDlg = new KPasswordDialog(nullptr, KPasswordDialog::ShowKeepPassword); passDlg->setPrompt(i18n("This archive is encrypted, please supply the password:") ), passDlg->setUsername(user); passDlg->setPassword(password); if (passDlg->exec() == KPasswordDialog::Accepted) { password = passDlg->password(); if (keep) { if (!KWallet::Wallet::isOpen(KWallet::Wallet::NetworkWallet()) && wallet != nullptr) { delete wallet; wallet = nullptr; } if (openWallet()) { bool ok = true; if (!wallet->hasFolder(KWallet::Wallet::PasswordFolder())) ok = wallet->createFolder(KWallet::Wallet::PasswordFolder()); if (ok) { wallet->setFolder(KWallet::Wallet::PasswordFolder()); QMap map; map.insert("login", "archive"); map.insert("password", password); wallet->writeMap(key, map); } } } delete passDlg; return password; } delete passDlg; return ""; } bool KRarcHandler::isArchive(const QUrl &url) { QString protocol = url.scheme(); if (arcProtocols.indexOf(protocol) != -1) return true; else return false; } QString KRarcHandler::getType(bool &encrypted, QString fileName, const QString& mime, bool checkEncrypted, bool fast) { QString result = detectArchive(encrypted, std::move(fileName), checkEncrypted, fast); if (result.isNull()) { // Then the type is based on the mime type return getShortTypeFromMime(mime); } return result; } bool KRarcHandler::checkStatus(const QString& type, int exitCode) { return KrArcBaseManager::checkStatus(type, exitCode); } void KRarcHandler::checkIf7zIsEncrypted(bool &encrypted, QString fileName) { Kr7zEncryptionChecker proc; // TODO incorporate all this in Kr7zEncryptionChecker proc << KrServices::fullPathName("7z") << "-y" << "t"; proc << fileName; proc.start(); proc.waitForFinished(); encrypted = proc.isEncrypted(); } diff --git a/krusader/Archive/krarchandler.h b/krusader/Archive/krarchandler.h index cdd81470..ec66f256 100644 --- a/krusader/Archive/krarchandler.h +++ b/krusader/Archive/krarchandler.h @@ -1,87 +1,87 @@ /***************************************************************************** * Copyright (C) 2001 Shie Erlich * * Copyright (C) 2001 Rafi Yanai * * Copyright (C) 2004-2019 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 KRARCHANDLER_H #define KRARCHANDLER_H // QtCore #include #include #include #include #include "../../krArc/krarcbasemanager.h" namespace KWallet { class Wallet; } class KRarcObserver : public QObject { Q_OBJECT public: ~KRarcObserver() override = default; virtual void processEvents() = 0; virtual void subJobStarted(const QString & jobTitle, int count) = 0; virtual void subJobStopped() = 0; virtual bool wasCancelled() = 0; virtual void error(const QString & error) = 0; virtual void detailedError(const QString & error, const QString & details) = 0; public slots: virtual void incrementProgress(int) = 0; }; class KRarcHandler: public QObject, public KrArcBaseManager { Q_OBJECT public: // return the number of files in the archive static long arcFileCount(const QString& archive, const QString& type, const QString& password, KRarcObserver *observer); // unpack an archive to destination directory static bool unpack(QString archive, const QString& type, const QString& password, const QString& dest, KRarcObserver *observer ); // pack an archive to destination directory static bool pack(QStringList fileNames, QString type, const QString& dest, long count, QMap extraProps, KRarcObserver *observer ); // test an archive static bool test(const QString& archive, const QString& type, const QString& password, KRarcObserver *observer, long count = 0L ); // returns `true` if the right unpacker exist in the system static bool arcSupported(QString type); // return the list of supported packers static QStringList supportedPackers(); // returns `true` if the url is an archive (ie: tar:/home/test/file.tar.bz2) static bool isArchive(const QUrl &url); // used to determine the type of the archive QString getType(bool &encrypted, QString fileName, const QString& mime, bool checkEncrypted = true, bool fast = false); // queries the password from the user static QString getPassword(const QString& path); // detects the archive type - void checkIf7zIsEncrypted(bool &, QString) Q_DECL_OVERRIDE; + void checkIf7zIsEncrypted(bool &, QString) override; private: //! checks if a returned status ("exit code") of an archiving-related process is OK static bool checkStatus(const QString& type, int exitCode); static bool openWallet(); static KWallet::Wallet * wallet; }; #endif diff --git a/krusader/Archive/packjob.h b/krusader/Archive/packjob.h index 358dfa4f..1420064b 100644 --- a/krusader/Archive/packjob.h +++ b/krusader/Archive/packjob.h @@ -1,125 +1,125 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * Copyright (C) 2009-2019 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 PACKJOB_H #define PACKJOB_H // QtCore #include #include "abstractthreadedjob.h" class PackThread; class TestArchiveThread; class UnpackThread; class PackJob : public AbstractThreadedJob { Q_OBJECT private: PackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps); public: static PackJob * createPacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps); }; class PackThread : public AbstractJobThread { Q_OBJECT public: PackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps); ~PackThread() override = default; protected slots: - void slotStart() Q_DECL_OVERRIDE; + void slotStart() override; private: QUrl _sourceUrl; QUrl _destUrl; QStringList _fileNames; QString _type; QMap _packProperties; }; class TestArchiveJob : public AbstractThreadedJob { Q_OBJECT private: TestArchiveJob(const QUrl &srcUrl, const QStringList & fileNames); public: static TestArchiveJob * testArchives(const QUrl &srcUrl, const QStringList & fileNames); }; class TestArchiveThread : public AbstractJobThread { Q_OBJECT public: TestArchiveThread(const QUrl &srcUrl, const QStringList & fileNames); ~TestArchiveThread() override = default; protected slots: - void slotStart() Q_DECL_OVERRIDE; + void slotStart() override; private: QUrl _sourceUrl; QStringList _fileNames; }; class UnpackJob : public AbstractThreadedJob { Q_OBJECT private: UnpackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames); public: static UnpackJob * createUnpacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames); }; class UnpackThread : public AbstractJobThread { Q_OBJECT public: UnpackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames); ~UnpackThread() override = default; protected slots: - void slotStart() Q_DECL_OVERRIDE; + void slotStart() override; private: QUrl _sourceUrl; QUrl _destUrl; QStringList _fileNames; }; #endif // __PACK_JOB_H__ diff --git a/krusader/BookMan/krbookmarkhandler.h b/krusader/BookMan/krbookmarkhandler.h index 86350545..5c6d3cb9 100644 --- a/krusader/BookMan/krbookmarkhandler.h +++ b/krusader/BookMan/krbookmarkhandler.h @@ -1,101 +1,101 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 KRBOOKMARKHANDLER_H #define KRBOOKMARKHANDLER_H // QtCore #include #include #include #include #include // QtXml #include // QtWidgets #include #include #include #include "krbookmark.h" class KActionCollection; class KBookmarkManager; class KrMainWindow; class KrBookmarkHandler: public QObject { Q_OBJECT friend class KrAddBookmarkDlg; enum Actions { BookmarkCurrent = 0, ManageBookmarks }; public: explicit KrBookmarkHandler(KrMainWindow *mainWindow); ~KrBookmarkHandler() override; void populate(QMenu *menu); void addBookmark(KrBookmark *bm, KrBookmark *parent = nullptr); void bookmarkCurrent(QUrl url); protected: void deleteBookmark(KrBookmark *bm); void importFromFile(); bool importFromFileBookmark(QDomElement &e, KrBookmark *parent, const QString& path, QString *errorMsg); bool importFromFileFolder(QDomNode &first, KrBookmark *parent, const QString& path, QString *errorMsg); void exportToFile(); void exportToFileFolder(QDomDocument &doc, QDomElement &parent, KrBookmark *folder); void exportToFileBookmark(QDomDocument &doc, QDomElement &where, KrBookmark *bm); void clearBookmarks(KrBookmark *root, bool removeBookmarks = true); void buildMenu(KrBookmark *parent, QMenu *menu, int depth = 0); - bool eventFilter(QObject *obj, QEvent *ev) Q_DECL_OVERRIDE; + bool eventFilter(QObject *obj, QEvent *ev) override; void rightClicked(QMenu *menu, KrBookmark *bm); void rightClickOnSpecialBookmark(); void removeReferences(KrBookmark *root, KrBookmark *bmToRemove); protected slots: void bookmarksChanged(const QString&, const QString&); void slotActivated(const QUrl &url); private: KrMainWindow *_mainWindow; KActionCollection *_collection, *_privateCollection; KrBookmark *_root; // the whole KBookmarkManager is an ugly hack. use it until we have our own KBookmarkManager *manager; bool _middleClick; // if true, the user clicked the middle button to open the bookmark QPointer _mainBookmarkPopup; // main bookmark popup menu QList _specialBookmarks; // the action list of the special bookmarks QWidgetAction *_quickSearchAction; ///< Search bar container action QLineEdit *_quickSearchBar; ///< Search bar containing current query QMenu *_quickSearchMenu; ///< The menu where the search is performed QHash _quickSearchOriginalActionTitles; ///< Saved original action text values to restore after search void _setQuickSearchText(const QString &text); QString _quickSearchText() const; static void _highlightAction(QAction *action, bool isMatched = true); void _resetActionTextAndHighlighting(); }; Q_DECLARE_METATYPE(KrBookmark *) #endif // KRBOOKMARK_HANDLER_H diff --git a/krusader/Dialogs/checksumdlg.h b/krusader/Dialogs/checksumdlg.h index da1d5ee7..fb826db8 100644 --- a/krusader/Dialogs/checksumdlg.h +++ b/krusader/Dialogs/checksumdlg.h @@ -1,180 +1,180 @@ /***************************************************************************** * Copyright (C) 2005 Shie Erlich * * Copyright (C) 2007-2008 Csaba Karai * * Copyright (C) 2008 Jonas Bähr * * Copyright (C) 2005-2019 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 CHECKSUMDLG_H #define CHECKSUMDLG_H // QtCore #include #include #include // QtWidgets #include #include #include #include #include class KrListWidget; class KrTreeWidget; /** * Perform checksum operations: Creation of checksums or verifying files with a checksum file. * * The dialogs are not modal. The used checksum tools only support local files which are expected to * be in one directory (specified by 'path'). */ class Checksum { public: static void startCreationWizard(const QString &path, const QStringList &fileNames); static void startVerifyWizard(const QString &path, const QString &checksumFile = QString()); }; namespace CHECKSUM_ { // private namespace /** Wrapper for KProcess to handle errors and output. */ class ChecksumProcess : public KProcess { Q_OBJECT public: ChecksumProcess(QObject *parent, const QString &path); ~ChecksumProcess() override; QStringList stdOutput() const { return m_outputLines; } QStringList errOutput() const { return m_errorLines; } signals: void resultReady(); private slots: void slotError(QProcess::ProcessError error); void slotFinished(int, QProcess::ExitStatus exitStatus); private: QStringList m_outputLines; QStringList m_errorLines; QTemporaryFile m_tmpOutFile; QTemporaryFile m_tmpErrFile; }; /** Base class for common code in creation and verify wizard. */ class ChecksumWizard : public QWizard { Q_OBJECT public: explicit ChecksumWizard(const QString &path); ~ChecksumWizard() override; private slots: void slotCurrentIdChanged(int id); protected: virtual QWizardPage *createIntroPage() = 0; virtual QWizardPage *createResultPage() = 0; virtual void onIntroPage() = 0; virtual void onProgressPage() = 0; virtual void onResultPage() = 0; QWizardPage *createProgressPage(const QString &title); bool checkExists(const QString& type); void runProcess(const QString &type, const QStringList &args); void addChecksumLine(KrTreeWidget *tree, const QString &line); const QString m_path; ChecksumProcess *m_process; QMap m_checksumTools; // extension/typ-name -> binary name int m_introId, m_progressId, m_resultId; }; class CreateWizard : public ChecksumWizard { Q_OBJECT public: CreateWizard(const QString &path, const QStringList &_files); public slots: - void accept() Q_DECL_OVERRIDE; + void accept() override; private: - QWizardPage *createIntroPage() Q_DECL_OVERRIDE; - QWizardPage *createResultPage() Q_DECL_OVERRIDE; + QWizardPage *createIntroPage() override; + QWizardPage *createResultPage() override; - void onIntroPage() Q_DECL_OVERRIDE; - void onProgressPage() Q_DECL_OVERRIDE; - void onResultPage() Q_DECL_OVERRIDE; + void onIntroPage() override; + void onProgressPage() override; + void onResultPage() override; void createChecksums(); bool savePerFile(); bool saveChecksumFile(const QStringList &data, const QString &filename = QString()); const QStringList m_fileNames; QFutureWatcher m_listFilesWatcher; QString m_suggestedFilePath; // intro page KComboBox *m_methodBox; // result page KrTreeWidget *m_hashesTreeWidget; QLabel *m_errorLabel; KrListWidget *m_errorListWidget; QCheckBox *m_onePerFileBox; }; class VerifyWizard : public ChecksumWizard { Q_OBJECT public: VerifyWizard(const QString &path, const QString &inputFile); private slots: void slotChecksumPathChanged(const QString &path); private: - QWizardPage *createIntroPage() Q_DECL_OVERRIDE; - QWizardPage *createResultPage() Q_DECL_OVERRIDE; + QWizardPage *createIntroPage() override; + QWizardPage *createResultPage() override; - void onIntroPage() Q_DECL_OVERRIDE; - void onProgressPage() Q_DECL_OVERRIDE; - void onResultPage() Q_DECL_OVERRIDE; + void onIntroPage() override; + void onProgressPage() override; + void onResultPage() override; bool isSupported(const QString &path); QString m_checksumFile; // intro page KrTreeWidget *m_hashesTreeWidget; // result page QLabel *m_outputLabel; KrListWidget *m_outputListWidget; }; } // NAMESPACE CHECKSUM_ #endif // CHECKSUMDLG_H diff --git a/krusader/Dialogs/krdialogs.h b/krusader/Dialogs/krdialogs.h index f6915ec1..a5c09ea5 100644 --- a/krusader/Dialogs/krdialogs.h +++ b/krusader/Dialogs/krdialogs.h @@ -1,119 +1,119 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KRDIALOGS_H #define KRDIALOGS_H // QtCore #include #include // QtWidgets #include #include #include #include #include #include #include // QtGui #include #include #include #include #include /** \class KChooseDir * Used for asking the user for a folder. * example: * \code * QUrl u = KChooseDir::getDir("target folder", "/suggested/path", ACTIVE_PANEL->virtualPath()); * if (u.isEmpty()) { * // user canceled (either by pressing cancel, or esc * } else { * // do you thing here: you've got a safe url to use * } * \endcode */ class KChooseDir { public: struct ChooseResult { QUrl url; bool enqueue; }; /** * \param text - description of the info requested from the user * \param url - a suggested url to appear in the box as a default choice * \param cwd - a path which is the current working directory (usually ACTIVE_PANEL->virtualPath()). * this is used for completion of partial urls */ static QUrl getFile(const QString &text, const QUrl &url, const QUrl &cwd); static QUrl getDir(const QString &text, const QUrl &url, const QUrl &cwd); static ChooseResult getCopyDir(const QString &text, const QUrl &url, const QUrl &cwd); private: static QUrl get(const QString &text, const QUrl &url, const QUrl &cwd, KFile::Modes mode); }; class KUrlRequesterDlgForCopy : public QDialog { Q_OBJECT public: KUrlRequesterDlgForCopy(const QUrl& url, const QString& text, QWidget *parent, bool modal = true); QUrl selectedURL() const; bool isQueued() { return queueStart; } KUrlRequester *urlRequester(); protected: - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) override; private slots: void slotQueueButtonClicked(); void slotTextChanged(const QString &); private: KUrlRequester *urlRequester_; QPushButton *okButton; bool queueStart = false; }; class KRGetDate : public QDialog { Q_OBJECT public: explicit KRGetDate(QDate date = QDate::currentDate(), QWidget *parent = nullptr); QDate getDate(); private slots: void setDate(QDate); private: KDatePicker *dateWidget; QDate chosenDate, originalDate; }; #endif diff --git a/krusader/Dialogs/krpleasewait.h b/krusader/Dialogs/krpleasewait.h index 0319a579..dd6133c4 100644 --- a/krusader/Dialogs/krpleasewait.h +++ b/krusader/Dialogs/krpleasewait.h @@ -1,81 +1,81 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KRPLEASEWAIT_H #define KRPLEASEWAIT_H // QtCore #include #include // QtGui #include // QtWidgets #include #include class KRPleaseWait; class KRPleaseWaitHandler : public QObject { Q_OBJECT public: explicit KRPleaseWaitHandler(QWidget *parentWindow); public slots: void startWaiting(const QString& msg, int count = 0, bool cancel = false); void stopWait(); void cycleProgress(); void incProgress(int i); void killJob(); void setJob(KIO::Job* j); bool wasCancelled() const { return _wasCancelled; } private: QWidget *_parentWindow; QPointer job; KRPleaseWait * dlg; bool cycle, cycleMutex, incMutex, _wasCancelled; }; class KRPleaseWait : public QProgressDialog { Q_OBJECT public: KRPleaseWait(const QString& msg, QWidget *parent, int count = 0 , bool cancel = false); public slots: void incProgress(int howMuch); void cycleProgress(); protected: bool inc; QTimer* timer; - void closeEvent(QCloseEvent * e) Q_DECL_OVERRIDE; + void closeEvent(QCloseEvent * e) override; bool canClose; }; #endif diff --git a/krusader/Dialogs/krspecialwidgets.h b/krusader/Dialogs/krspecialwidgets.h index cbd7f99b..e35b482f 100644 --- a/krusader/Dialogs/krspecialwidgets.h +++ b/krusader/Dialogs/krspecialwidgets.h @@ -1,127 +1,127 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KRSPECIALWIDGETS_H #define KRSPECIALWIDGETS_H // QtCore #include // QtGui #include #include #include #include // QtWidgets #include #include #include #include class KRPieSlice; class KRPie : public QWidget { Q_OBJECT public: explicit KRPie(KIO::filesize_t _totalSize, QWidget *parent = nullptr); void addSlice(KIO::filesize_t size, QString label); protected: - void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *) override; private: QList slices; KIO::filesize_t totalSize, sizeLeft; static QColor colors[ 12 ]; }; class KRFSDisplay : public QWidget { Q_OBJECT public: // this constructor is used for a mounted filesystem KRFSDisplay(QWidget *parent, QString _alias, QString _realName, KIO::filesize_t _total, KIO::filesize_t _free); // this one is for an unmounted/supermount file system KRFSDisplay(QWidget *parent, QString _alias, QString _realName, bool sm = false); // the last one is used inside MountMan(R), when no filesystem is selected explicit KRFSDisplay(QWidget *parent); inline void setTotalSpace(KIO::filesize_t t) { totalSpace = t; } inline void setFreeSpace(KIO::filesize_t t) { freeSpace = t; } inline void setAlias(QString a) { alias = std::move(a); } inline void setRealName(QString r) { realName = std::move(r); } inline void setMounted(bool m) { mounted = m; } inline void setEmpty(bool e) { empty = e; } inline void setSupermount(bool s) { supermount = s; } protected: - void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *) override; private: KIO::filesize_t totalSpace, freeSpace; QString alias, realName; bool mounted, empty, supermount; }; class KRPieSlice { public: KRPieSlice(float _perct, QColor _color, QString _label) : perct(_perct), color(std::move(_color)), label(std::move(_label)) {} inline QColor getColor() { return color; } inline float getPerct() { return perct; } inline QString getLabel() { return label; } inline void setPerct(float _perct) { perct = _perct; } inline void setLabel(QString _label) { label = std::move(_label); } private: float perct; QColor color; QString label; }; #endif diff --git a/krusader/Dialogs/krspwidgets.h b/krusader/Dialogs/krspwidgets.h index d53bb4eb..fd84db7f 100644 --- a/krusader/Dialogs/krspwidgets.h +++ b/krusader/Dialogs/krspwidgets.h @@ -1,83 +1,83 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KRSPWIDGETS_H #define KRSPWIDGETS_H // QtCore #include // QtGui #include #include #include #include "krmaskchoice.h" #include "newftpgui.h" #include "../FileSystem/krquery.h" class KRMaskChoiceSub; class KRSpWidgets { friend class KRMaskChoiceSub; public: KRSpWidgets(); static KRQuery getMask(const QString& caption, bool nameOnly = false, QWidget * parent = 0); // get file-mask for (un)selecting files static QUrl newFTP(); private: static QStringList maskList; // used by KRMaskChoiceSub }; /////////////////////////// newFTPSub /////////////////////////////////////// class newFTPSub : public newFTPGUI { public: newFTPSub(); protected: - void reject() Q_DECL_OVERRIDE; - void accept() Q_DECL_OVERRIDE; + void reject() override; + void accept() override; }; /////////////////////////// KRMaskChoiceSub ///////////////////////////////// // Inherits KRMaskChoice's generated code to fully implement the functions // ///////////////////////////////////////////////////////////////////////////// class KRMaskChoiceSub : public KRMaskChoice { public: explicit KRMaskChoiceSub(QWidget * parent = 0); public slots: - void addSelection() Q_DECL_OVERRIDE; - void deleteSelection() Q_DECL_OVERRIDE; - void clearSelections() Q_DECL_OVERRIDE; - void acceptFromList(QListWidgetItem *i) Q_DECL_OVERRIDE; - void currentItemChanged(QListWidgetItem *i) Q_DECL_OVERRIDE; + void addSelection() override; + void deleteSelection() override; + void clearSelections() override; + void acceptFromList(QListWidgetItem *i) override; + void currentItemChanged(QListWidgetItem *i) override; protected: - void reject() Q_DECL_OVERRIDE; - void accept() Q_DECL_OVERRIDE; + void reject() override; + void accept() override; }; #endif diff --git a/krusader/Dialogs/krsqueezedtextlabel.h b/krusader/Dialogs/krsqueezedtextlabel.h index e753d755..e8284fa0 100644 --- a/krusader/Dialogs/krsqueezedtextlabel.h +++ b/krusader/Dialogs/krsqueezedtextlabel.h @@ -1,70 +1,70 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 KRSQUEEZEDTEXTLABEL_H #define KRSQUEEZEDTEXTLABEL_H // QtGui #include #include #include #include class QMouseEvent; class QDragEnterEvent; class QPaintEvent; /** This class overloads KSqueezedTextLabel and simply adds a clicked signal, so that users will be able to click the label and switch focus between panels. NEW: a special setText() method allows to choose which part of the string should be displayed (example: make sure that search results won't be cut out) */ class KrSqueezedTextLabel : public KSqueezedTextLabel { Q_OBJECT public: explicit KrSqueezedTextLabel(QWidget *parent = nullptr); ~KrSqueezedTextLabel() override; public slots: void setText(const QString &text, int index = -1, int length = -1); signals: void clicked(QMouseEvent *); /**< emitted when someone clicks on the label */ protected: - void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE { + void resizeEvent(QResizeEvent *) override { squeezeTextToLabel(_index, _length); } - void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; - void paintEvent(QPaintEvent * e) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *e) override; + void paintEvent(QPaintEvent * e) override; void squeezeTextToLabel(int index = -1, int length = -1); QString fullText; private: int _index, _length; }; #endif diff --git a/krusader/Dialogs/kurllistrequester.h b/krusader/Dialogs/kurllistrequester.h index af43d446..d8c21534 100644 --- a/krusader/Dialogs/kurllistrequester.h +++ b/krusader/Dialogs/kurllistrequester.h @@ -1,78 +1,78 @@ /***************************************************************************** * Copyright (C) 2005 Csaba Karai * * Copyright (C) 2005-2019 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 KURLLISTREQUESTER_H #define KURLLISTREQUESTER_H // QtGui #include // QtWidgets #include #include #include #include #include "../GUI/krlistwidget.h" /** * Widget for letting the user define a list of URLs. */ class KURLListRequester : public QWidget { Q_OBJECT public: enum Mode { RequestFiles, RequestDirs }; explicit KURLListRequester(Mode requestMode, QWidget *parent = nullptr); QList urlList(); void setUrlList(const QList &); KLineEdit *lineEdit() { return urlLineEdit; } KrListWidget *listBox() { return urlListBox; } void setCompletionDir(const QUrl &dir) { completion.setDir(dir); } signals: void checkValidity(QString &text, QString &error); void changed(); protected slots: void slotAdd(); void slotBrowse(); void slotRightClicked(QListWidgetItem *, const QPoint &); protected: - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) override; void deleteSelectedItems(); Mode mode; KLineEdit *urlLineEdit; KrListWidget *urlListBox; QToolButton *urlAddBtn; QToolButton *urlBrowseBtn; KUrlCompletion completion; }; #endif /* __KURLLISTREQUESTER_H__ */ diff --git a/krusader/Dialogs/newftpgui.h b/krusader/Dialogs/newftpgui.h index ddbeef6b..dbaf3af5 100644 --- a/krusader/Dialogs/newftpgui.h +++ b/krusader/Dialogs/newftpgui.h @@ -1,68 +1,68 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2009 Fathi Boudra * * Copyright (C) 2004-2019 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 NEWFTPGUI_H #define NEWFTPGUI_H // QtWidgets #include #include #include #include #include #include /** * The "New Network Connection" dialog */ class newFTPGUI : public QDialog { Q_OBJECT public: explicit newFTPGUI(QWidget *parent = nullptr); ~newFTPGUI() override; KComboBox* prefix; KHistoryComboBox* url; QSpinBox* port; KLineEdit* username; KLineEdit* password; protected: - bool event(QEvent *) Q_DECL_OVERRIDE; + bool event(QEvent *) override; private slots: void slotTextChanged(const QString &); private: QLabel* iconLabel; QLabel* aboutLabel; QLabel* protocolLabel; QLabel* passwordLabel; QLabel* hostLabel; QLabel* usernameLabel; QLabel* portLabel; }; #endif diff --git a/krusader/Dialogs/packgui.h b/krusader/Dialogs/packgui.h index b1d06b47..ec41fa8b 100644 --- a/krusader/Dialogs/packgui.h +++ b/krusader/Dialogs/packgui.h @@ -1,45 +1,45 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 PACKGUI_H #define PACKGUI_H #include "packguibase.h" class PackGUI : public PackGUIBase { Q_OBJECT public: PackGUI(const QString& defaultName, const QString& defaultPath, int noOfFiles, const QString& filename = ""); public slots: - void browse() Q_DECL_OVERRIDE; + void browse() override; protected slots: - void accept() Q_DECL_OVERRIDE; - void reject() Q_DECL_OVERRIDE; + void accept() override; + void reject() override; public: static QString filename, destination, type; static QMap extraProps; }; #endif diff --git a/krusader/Dialogs/percentalsplitter.h b/krusader/Dialogs/percentalsplitter.h index 12e4dbe6..80c4c48e 100644 --- a/krusader/Dialogs/percentalsplitter.h +++ b/krusader/Dialogs/percentalsplitter.h @@ -1,50 +1,50 @@ /***************************************************************************** * Copyright (C) 2006 Csaba Karai * * Copyright (C) 2006-2019 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 PERCENTALSPLITTER_H #define PERCENTALSPLITTER_H // QtWidgets #include #include class PercentalSplitter : public QSplitter { Q_OBJECT public: explicit PercentalSplitter(QWidget * parent = nullptr); ~PercentalSplitter() override; QString toolTipString(int p); protected: - void showEvent(QShowEvent * event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent * event) override; protected slots: void slotSplitterMoved(int pos, int index); private: QLabel * label; int opaqueOldPos; QPoint labelLocation; }; #endif /* __PERCENTAL_SPLITTER__ */ diff --git a/krusader/DiskUsage/diskusage.h b/krusader/DiskUsage/diskusage.h index aee3bd7f..7f814d82 100644 --- a/krusader/DiskUsage/diskusage.h +++ b/krusader/DiskUsage/diskusage.h @@ -1,209 +1,209 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 DISKUSAGE_H #define DISKUSAGE_H // QtCore #include #include #include #include #include // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include "filelightParts/fileTree.h" #define VIEW_LINES 0 #define VIEW_DETAILED 1 #define VIEW_FILELIGHT 2 #define VIEW_LOADER 3 typedef QHash Properties; class DUListView; class DULines; class DUFilelight; class QMenu; class LoaderWidget; class FileItem; class FileSystem; class DiskUsage : public QStackedWidget { Q_OBJECT public: explicit DiskUsage(QString confGroup, QWidget *parent = 0); ~DiskUsage(); void load(const QUrl &dirName); void close(); void stopLoad(); bool isLoading() { return loading; } void setView(int view); int getActiveView() { return activeView; } Directory* getDirectory(QString path); File * getFile(const QString& path); QString getConfigGroup() { return configGroup; } void * getProperty(File *, const QString&); void addProperty(File *, const QString&, void *); void removeProperty(File *, const QString&); int exclude(File *file, bool calcPercents = true, int depth = 0); void includeAll(); int del(File *file, bool calcPercents = true, int depth = 0); QString getToolTip(File *); void rightClickMenu(const QPoint &, File *, QMenu * = 0, const QString& = QString()); void changeDirectory(Directory *dir); Directory* getCurrentDir(); File* getCurrentFile(); QPixmap getIcon(const QString& mime); QUrl getBaseURL() { return baseURL; } public slots: void dirUp(); void clear(); signals: void enteringDirectory(Directory *); void clearing(); void changed(File *); void changeFinished(); void deleted(File *); void deleteFinished(); void status(QString); void viewChanged(int); void loadFinished(bool); void newSearch(); protected slots: void slotLoadDirectory(); protected: QHash< QString, Directory * > contentMap; QHash< File *, Properties *> propertyMap; Directory* currentDirectory; KIO::filesize_t currentSize; - virtual void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; - virtual bool event(QEvent *) Q_DECL_OVERRIDE; + virtual void keyPressEvent(QKeyEvent *) override; + virtual bool event(QEvent *) override; int calculateSizes(Directory *dir = 0, bool emitSig = false, int depth = 0); int calculatePercents(bool emitSig = false, Directory *dir = 0 , int depth = 0); int include(Directory *dir, int depth = 0); void createStatus(); void executeAction(int, File * = 0); QUrl baseURL; //< the base URL of loading DUListView *listView; DULines *lineView; DUFilelight *filelightView; LoaderWidget *loaderView; Directory *root; int activeView; QString configGroup; bool first; bool loading; bool abortLoading; bool clearAfterAbort; bool deleting; QStack directoryStack; QStack parentStack; FileSystem *searchFileSystem; FileItem *currentFileItem; QList fileItems; Directory *currentParent; QString dirToCheck; int fileNum; int dirNum; int viewBeforeLoad; QTimer loadingTimer; }; class LoaderWidget : public QScrollArea { Q_OBJECT public: explicit LoaderWidget(QWidget *parent = 0); void init(); void setCurrentURL(const QUrl &url); void setValues(int fileNum, int dirNum, KIO::filesize_t total); bool wasCancelled() { return cancelled; } public slots: void slotCancelled(); protected: QLabel *totalSize; QLabel *files; QLabel *directories; KSqueezedTextLabel *searchedDirectory; QWidget *widget; bool cancelled; }; #endif /* __DISK_USAGE_GUI_H__ */ diff --git a/krusader/DiskUsage/diskusagegui.h b/krusader/DiskUsage/diskusagegui.h index ca1ef302..375721db 100644 --- a/krusader/DiskUsage/diskusagegui.h +++ b/krusader/DiskUsage/diskusagegui.h @@ -1,87 +1,87 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 DISKUSAGEGUI_H #define DISKUSAGEGUI_H // QtCore #include // QtGui #include // QtWidgets #include #include #include #include #include "diskusage.h" class DiskUsageGUI : public QDialog { Q_OBJECT public: explicit DiskUsageGUI(const QUrl &openDir); ~DiskUsageGUI() override = default; void askDirAndShow(); protected slots: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + void closeEvent(QCloseEvent *event) override; protected: - void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *e) override; private slots: bool askDir(); void slotLoadUsageInfo(); void slotStatus(const QString&); void slotSelectLinesView() { diskUsage->setView(VIEW_LINES); } void slotSelectListView() { diskUsage->setView(VIEW_DETAILED); } void slotSelectFilelightView() { diskUsage->setView(VIEW_FILELIGHT); } void slotViewChanged(int view); void slotLoadFinished(bool); private: void enableButtons(bool); DiskUsage *diskUsage; QUrl baseDirectory; KSqueezedTextLabel *status; QToolButton *btnNewSearch; QToolButton *btnRefresh; QToolButton *btnDirUp; QToolButton *btnLines; QToolButton *btnDetailed; QToolButton *btnFilelight; int sizeX; int sizeY; bool exitAtFailure; }; #endif /* __DISK_USAGE_GUI_H__ */ diff --git a/krusader/DiskUsage/dufilelight.h b/krusader/DiskUsage/dufilelight.h index 17b2b74f..32b51630 100644 --- a/krusader/DiskUsage/dufilelight.h +++ b/krusader/DiskUsage/dufilelight.h @@ -1,79 +1,79 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 DUFILELIGHT_H #define DUFILELIGHT_H // QtGui #include #include "diskusage.h" #include "radialMap/widget.h" #include "filelightParts/Config.h" class DUFilelight : public RadialMap::Widget { Q_OBJECT public: explicit DUFilelight(DiskUsage *usage); File * getCurrentFile(); public slots: void slotDirChanged(Directory *); void clear(); void slotChanged(File *); void slotRefresh(); protected slots: void slotAboutToShow(int); void schemeRainbow() { setScheme(Filelight::Rainbow); } void schemeHighContrast() { setScheme(Filelight::HighContrast); } void schemeKDE() { setScheme(Filelight::KDE); } void increaseContrast(); void decreaseContrast(); void changeAntiAlias(); void showSmallFiles(); void varyLabelFontSizes(); void minFontSize(); protected: - void mousePressEvent(QMouseEvent*) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent*) override; void setScheme(Filelight::MapScheme); DiskUsage *diskUsage; Directory *currentDir; private: bool refreshNeeded; }; #endif /* __DU_FILELIGHT_H__ */ diff --git a/krusader/DiskUsage/dulines.cpp b/krusader/DiskUsage/dulines.cpp index f80e10fc..114d767c 100644 --- a/krusader/DiskUsage/dulines.cpp +++ b/krusader/DiskUsage/dulines.cpp @@ -1,535 +1,535 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 #include "../compat.h" class DULinesItemDelegate : public QItemDelegate { public: explicit DULinesItemDelegate(QObject *parent = nullptr) : QItemDelegate(parent) {} - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE { + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 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.QFONTMETRICS_WIDTH(display) + iconSize.width(); bool truncd = false; QRect rct = option.rect; if (rct.width() > pos) { rct.setX(rct.x() + pos); if (fm.QFONTMETRICS_WIDTH(renderedText) > rct.width()) { truncd = true; int points = fm.QFONTMETRICS_WIDTH("..."); while (!renderedText.isEmpty() && (fm.QFONTMETRICS_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, const QString& label1, const QString& label2, const 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, const QString& label1, const QString& label2, const QString& label3) : QTreeWidgetItem(parent, after), diskUsage(diskUsageIn), file(fileItem) { setText(0, label1); setText(1, label2); setText(2, label3); setTextAlignment(1, Qt::AlignRight); } - bool operator<(const QTreeWidgetItem &other) const Q_DECL_OVERRIDE { + bool operator<(const QTreeWidgetItem &other) const override { int column = treeWidget() ? treeWidget()->sortColumn() : 0; if (text(0) == "..") return true; const auto *compWith = dynamic_cast< const DULinesItem * >(&other); if (compWith == nullptr) 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()).QFONTMETRICS_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: { auto *he = dynamic_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 = (dynamic_cast(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 = nullptr; if (!(dirEntry->parent() == nullptr)) { 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 == nullptr) 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 == nullptr) 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) != "..") { auto *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 = (dynamic_cast(item))->getFile(); if (fileItem->isDir()) diskUsage->changeDirectory(dynamic_cast(fileItem)); return true; } else { auto *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 = nullptr; if (item && item->text(0) != "..") file = (dynamic_cast(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 == nullptr || item->text(0) == "..") return nullptr; return (dynamic_cast(item))->getFile(); } void DULines::slotChanged(File * item) { QTreeWidgetItemIterator it(this); while (*it) { QTreeWidgetItem *lvitem = *it; it++; if (lvitem->text(0) != "..") { auto *duItem = dynamic_cast(lvitem); if (duItem->getFile() == item) { setSortingEnabled(false); duItem->setHidden(item->isExcluded()); duItem->setText(1, item->percent()); if (!refreshNeeded) { refreshNeeded = true; 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) != "..") { auto *duItem = dynamic_cast(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/DiskUsage/dulines.h b/krusader/DiskUsage/dulines.h index a565176d..307dc499 100644 --- a/krusader/DiskUsage/dulines.h +++ b/krusader/DiskUsage/dulines.h @@ -1,78 +1,78 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 DULINES_H #define DULINES_H // QtGui #include #include #include #include #include "diskusage.h" #include "../GUI/krtreewidget.h" class DULinesToolTip; class DULinesItemDelegate; class DULines : public KrTreeWidget { Q_OBJECT public: explicit DULines(DiskUsage *usage); ~DULines() override; File * getCurrentFile(); public slots: void slotDirChanged(Directory *dirEntry); void sectionResized(int); void slotRightClicked(QTreeWidgetItem *, const QPoint &); void slotChanged(File *); void slotDeleted(File *); void slotShowFileSizes(); void slotRefresh(); protected: DiskUsage *diskUsage; - bool event(QEvent * event) Q_DECL_OVERRIDE; - void mouseDoubleClickEvent(QMouseEvent * e) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; - void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE; + bool event(QEvent * event) override; + void mouseDoubleClickEvent(QMouseEvent * e) override; + void keyPressEvent(QKeyEvent *e) override; + void resizeEvent(QResizeEvent *) override; private: QPixmap createPixmap(int percent, int maxPercent, int maxWidth); bool doubleClicked(QTreeWidgetItem * item); bool refreshNeeded; bool started; bool showFileSize; DULinesToolTip *toolTip; DULinesItemDelegate *itemDelegate; }; #endif /* __DU_LINES_H__ */ diff --git a/krusader/DiskUsage/dulistview.h b/krusader/DiskUsage/dulistview.h index 2473e18c..2d15ba6e 100644 --- a/krusader/DiskUsage/dulistview.h +++ b/krusader/DiskUsage/dulistview.h @@ -1,184 +1,184 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 DULISTVIEW_H #define DULISTVIEW_H // QtGui #include #include #include "../GUI/krtreewidget.h" #include "diskusage.h" class DUListViewItem : public QTreeWidgetItem { public: DUListViewItem(DiskUsage *diskUsageIn, File *fileIn, QTreeWidget * parent, const QString& label1, const QString& label2, const QString& label3, const QString& label4, const QString& label5, const QString& label6, const QString& label7, const QString& label8, const QString& label9) : QTreeWidgetItem(parent), diskUsage(diskUsageIn), file(fileIn) { setText(0, label1); setText(1, label2); setText(2, label3); setText(3, label4); setText(4, label5); setText(5, label6); setText(6, label7); setText(7, label8); setText(8, label9); setTextAlignment(1, Qt::AlignRight); setTextAlignment(2, Qt::AlignRight); setTextAlignment(3, Qt::AlignRight); setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); diskUsage->addProperty(file, "ListView-Ref", this); } DUListViewItem(DiskUsage *diskUsageIn, File *fileIn, QTreeWidgetItem * parent, const QString& label1, const QString& label2, const QString& label3, const QString& label4, const QString& label5, const QString& label6, const QString& label7, const QString& label8, const QString& label9) : QTreeWidgetItem(parent), diskUsage(diskUsageIn), file(fileIn) { setText(0, label1); setText(1, label2); setText(2, label3); setText(3, label4); setText(4, label5); setText(5, label6); setText(6, label7); setText(7, label8); setText(8, label9); setTextAlignment(1, Qt::AlignRight); setTextAlignment(2, Qt::AlignRight); setTextAlignment(3, Qt::AlignRight); setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); diskUsage->addProperty(file, "ListView-Ref", this); } DUListViewItem(DiskUsage *diskUsageIn, File *fileIn, QTreeWidget * parent, QTreeWidgetItem * after, const QString& label1, const QString& label2, const QString& label3, const QString& label4, const QString& label5, const QString& label6, const QString& label7, const QString& label8, const QString& label9) : QTreeWidgetItem(parent, after), diskUsage(diskUsageIn), file(fileIn) { setText(0, label1); setText(1, label2); setText(2, label3); setText(3, label4); setText(4, label5); setText(5, label6); setText(6, label7); setText(7, label8); setText(8, label9); setTextAlignment(1, Qt::AlignRight); setTextAlignment(2, Qt::AlignRight); setTextAlignment(3, Qt::AlignRight); setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); diskUsage->addProperty(file, "ListView-Ref", this); } DUListViewItem(DiskUsage *diskUsageIn, File *fileIn, QTreeWidgetItem * parent, QTreeWidgetItem * after, const QString& label1, const QString& label2, const QString& label3, const QString& label4, const QString& label5, const QString& label6, const QString& label7, const QString& label8, const QString& label9) : QTreeWidgetItem(parent, after), diskUsage(diskUsageIn), file(fileIn) { setText(0, label1); setText(1, label2); setText(2, label3); setText(3, label4); setText(4, label5); setText(5, label6); setText(6, label7); setText(7, label8); setText(8, label9); setTextAlignment(1, Qt::AlignRight); setTextAlignment(2, Qt::AlignRight); setTextAlignment(3, Qt::AlignRight); setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); diskUsage->addProperty(file, "ListView-Ref", this); } ~DUListViewItem() override { diskUsage->removeProperty(file, "ListView-Ref"); } - bool operator<(const QTreeWidgetItem &other) const Q_DECL_OVERRIDE { + bool operator<(const QTreeWidgetItem &other) const override { int column = treeWidget() ? treeWidget()->sortColumn() : 0; if (text(0) == "..") return true; const auto *compWith = dynamic_cast< const DUListViewItem * >(&other); if (compWith == nullptr) return false; switch (column) { case 1: case 2: return file->size() > compWith->file->size(); case 3: return file->ownSize() > compWith->file->ownSize(); case 5: return file->time() < compWith->file->time(); default: return text(column) < other.text(column); } } inline File * getFile() { return file; } private: DiskUsage *diskUsage; File *file; }; class DUListView : public KrTreeWidget { Q_OBJECT public: explicit DUListView(DiskUsage *usage); ~DUListView() override; File * getCurrentFile(); public slots: void slotDirChanged(Directory *); void slotChanged(File *); void slotDeleted(File *); void slotRightClicked(QTreeWidgetItem *, const QPoint &); void slotExpanded(QTreeWidgetItem *); protected: DiskUsage *diskUsage; - void mouseDoubleClickEvent(QMouseEvent * e) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void mouseDoubleClickEvent(QMouseEvent * e) override; + void keyPressEvent(QKeyEvent *e) override; private: void addDirectory(Directory *dirEntry, QTreeWidgetItem *parent); bool doubleClicked(QTreeWidgetItem * item); }; #endif /* __DU_LISTVIEW_H__ */ diff --git a/krusader/DiskUsage/filelightParts/fileTree.h b/krusader/DiskUsage/filelightParts/fileTree.h index 660ce50b..b70f8926 100644 --- a/krusader/DiskUsage/filelightParts/fileTree.h +++ b/krusader/DiskUsage/filelightParts/fileTree.h @@ -1,385 +1,385 @@ /***************************************************************************** * Copyright (C) 2004 Max Howell * * Copyright (C) 2004-2019 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 FILETREE_H #define FILETREE_H #include #include #include #include #include // TODO these are pointlessly general purpose now, make them incredibly specific typedef KIO::filesize_t FileSize; template class Iterator; template class ConstIterator; template class Chain; template class Link { public: explicit Link(T* const t) : prev(this), next(this), data(t) {} Link() : prev(this), next(this), data(0) {} //TODO unlinking is slow and you don't use it very much in this context. // ** Perhaps you can make a faster deletion system that doesn't bother tidying up first // ** and then you MUST call some kind of detach() function when you remove elements otherwise ~Link() { delete data; unlink(); } friend class Iterator; friend class ConstIterator; friend class Chain; private: void unlink() { prev->next = next; next->prev = prev; prev = next = this; } Link* prev; Link* next; T* data; //ensure only iterators have access to this }; template class Iterator { public: Iterator() : link(0) { } //**** remove this, remove this REMOVE THIS!!! dangerous as your implementation doesn't test for null links, always assumes they can be dereferenced explicit Iterator(Link *p) : link(p) { } bool operator==(const Iterator& it) const { return link == it.link; } bool operator!=(const Iterator& it) const { return link != it.link; } bool operator!=(const Link *p) const { return p != link; } //here we have a choice, really I should make two classes one const the other not const T* operator*() const { return link->data; } T* operator*() { return link->data; } Iterator& operator++() { link = link->next; return *this; } //**** does it waste time returning in places where we don't use the retval? bool isNull() const { return (link == 0); } //REMOVE WITH ABOVE REMOVAL you don't want null iterators to be possible void transferTo(Chain &chain) { chain.append(remove()); } T* remove() { //remove from list, delete Link, data is returned NOT deleted T* const d = link->data; Link* const p = link->prev; link->data = 0; delete link; link = p; //make iterator point to previous element, YOU must check this points to an element return d; } private: Link *link; }; template class ConstIterator { public: explicit ConstIterator(Link *p) : link(p) { } bool operator==(const Iterator& it) const { return link == it.link; } bool operator!=(const Iterator& it) const { return link != it.link; } bool operator!=(const Link *p) const { return p != link; } const T* operator*() const { return link->data; } ConstIterator& operator++() { link = link->next; return *this; } private: const Link *link; }; //**** try to make a generic list class and then a brief full list template that inlines // thus reducing code bloat template class Chain { public: Chain() { } virtual ~Chain() { empty(); } void append(T* const data) { Link* const link = new Link(data); link->prev = head.prev; link->next = &head; head.prev->next = link; head.prev = link; } void transferTo(Chain &c) { if (isEmpty()) return; Link* const first = head.next; Link* const last = head.prev; head.unlink(); first->prev = c.head.prev; c.head.prev->next = first; last->next = &c.head; c.head.prev = last; } void empty() { while (head.next != &head) { delete head.next; } } Iterator iterator() const { return Iterator(head.next); } ConstIterator constIterator() const { return ConstIterator(head.next); } const Link *end() const { return &head; } bool isEmpty() const { return (head.next == &head); } private: Link head; void operator=(const Chain&) {} }; class Directory; class File { protected: Directory *m_parent; //0 if this is treeRoot QString m_name; //< file name QString m_directory;//< the directory of the file FileSize m_size; //< size with subdirectories FileSize m_ownSize; //< size without subdirectories mode_t m_mode; //< file mode QString m_owner; //< file owner name QString m_group; //< file group name QString m_perm; //< file permissions string time_t m_time; //< file modification in time_t format bool m_symLink; //< true if the file is a symlink QString m_mimeType; //< file mimetype bool m_excluded; //< flag if the file is excluded from du int m_percent; //< percent flag public: File(Directory *parentIn, const QString &nameIn, const QString &dir, FileSize sizeIn, mode_t modeIn, const QString &ownerIn, const QString &groupIn, const QString &permIn, time_t timeIn, bool symLinkIn, const QString &mimeTypeIn) : m_parent(parentIn), m_name(nameIn), m_directory(dir), m_size(sizeIn), m_ownSize(sizeIn), m_mode(modeIn), m_owner(ownerIn), m_group(groupIn), m_perm(permIn), m_time(timeIn), m_symLink(symLinkIn), m_mimeType(mimeTypeIn), m_excluded(false), m_percent(-1) {} File(const QString &nameIn, FileSize sizeIn) : m_parent(0), m_name(nameIn), m_directory(QString()), m_size(sizeIn), m_ownSize(sizeIn), m_mode(0), m_owner(QString()), m_group(QString()), m_perm(QString()), m_time(-1), m_symLink(false), m_mimeType(QString()), m_excluded(false), m_percent(-1) { } virtual ~File() {} inline const QString & name() const { return m_name; } inline const QString & directory() const { return m_directory; } inline FileSize size() const { return m_excluded ? 0 : m_size; } inline FileSize ownSize() const { return m_excluded ? 0 : m_ownSize; } inline mode_t mode() const { return m_mode; } inline const QString & owner() const { return m_owner; } inline const QString & group() const { return m_group; } inline const QString & perm() const { return m_perm; } inline time_t time() const { return m_time; } inline const QString & mime() const { return m_mimeType; } inline bool isSymLink() const { return m_symLink; } virtual bool isDir() const { return false; } inline bool isExcluded() const { return m_excluded; } inline void exclude(bool flag) { m_excluded = flag; } inline int intPercent() const { return m_percent; } inline const QString percent() const { if (m_percent < 0) return "INV"; QString buf; buf.sprintf("%d.%02d%%", m_percent / 100, m_percent % 100); return buf; } inline void setPercent(int p) { m_percent = p; } inline const Directory* parent() const { return m_parent; } inline void setSizes(KIO::filesize_t totalSize, KIO::filesize_t ownSize) { m_ownSize = ownSize; m_size = totalSize; } enum UnitPrefix { kilo, mega, giga, tera }; static const FileSize DENOMINATOR[4]; static const char PREFIX[5][2]; QString fullPath(const Directory* = 0) const; QString humanReadableSize(UnitPrefix key = mega) const; static QString humanReadableSize(FileSize size, UnitPrefix Key = mega); friend class Directory; }; //TODO when you modify this to take into account hardlinks you should make the Chain layered not inherited class Directory : public Chain, public File { public: Directory(Directory *parentIn, const QString &nameIn, const QString &dir, FileSize sizeIn, mode_t modeIn, const QString &ownerIn, const QString &groupIn, const QString &permIn, time_t timeIn, bool symLinkIn, const QString &mimeTypeIn) : File(parentIn, nameIn, dir, sizeIn, modeIn, ownerIn, groupIn, permIn, timeIn, symLinkIn, mimeTypeIn), m_fileCount(0) {} Directory(const QString &name, QString url) : File(name, 0), m_fileCount(0) { m_directory = url; } virtual ~Directory() {} - virtual bool isDir() const Q_DECL_OVERRIDE { + virtual bool isDir() const override { return true; } void append(File *p) { ++m_fileCount; Directory *parent = m_parent; while (parent) { parent->m_fileCount++; parent = parent->m_parent; } Chain::append(p); p->m_parent = this; } void remove(File *p) { for (Iterator it = Chain::iterator(); it != Chain::end(); ++it) if ((*it) == p) { --m_fileCount; Directory *parent = m_parent; while (parent) { parent->m_fileCount--; parent = parent->m_parent; } it.remove(); break; } } uint fileCount() const { return m_fileCount; } private: Directory(const Directory&); void operator=(const Directory&); uint m_fileCount; }; #endif diff --git a/krusader/DiskUsage/radialMap/segmentTip.h b/krusader/DiskUsage/radialMap/segmentTip.h index 32aa0d65..c5053f7f 100644 --- a/krusader/DiskUsage/radialMap/segmentTip.h +++ b/krusader/DiskUsage/radialMap/segmentTip.h @@ -1,54 +1,54 @@ /***************************************************************************** * Copyright (C) 2003-2004 Max Howell * * Copyright (C) 2004-2019 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 SEGMENTTIP_H #define SEGMENTTIP_H // QtCore #include // QtGui #include // QtWidgets #include class File; class Directory; namespace RadialMap { class SegmentTip : public QWidget { public: explicit SegmentTip(uint); void updateTip(const File*, const Directory*); void moveto(QPoint, QWidget&, bool); private: - virtual bool eventFilter(QObject*, QEvent*) Q_DECL_OVERRIDE; - virtual bool event(QEvent*) Q_DECL_OVERRIDE; + virtual bool eventFilter(QObject*, QEvent*) override; + virtual bool event(QEvent*) override; uint m_cursorHeight; QPixmap m_pixmap; QString m_text; }; } #endif diff --git a/krusader/DiskUsage/radialMap/widget.h b/krusader/DiskUsage/radialMap/widget.h index e0c08cbe..31a49232 100644 --- a/krusader/DiskUsage/radialMap/widget.h +++ b/krusader/DiskUsage/radialMap/widget.h @@ -1,140 +1,140 @@ /***************************************************************************** * Copyright (C) 2004 Max Howell * * Copyright (C) 2004-2019 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 WIDGET_H #define WIDGET_H // QtCore #include #include // QtGui #include #include #include #include "segmentTip.h" template class Chain; class Directory; class File; class KJob; namespace RadialMap { class Segment; class Map : public QPixmap { public: Map(); ~Map() override; void make(const Directory *, bool = false); bool resize(const QRect&); bool isNull() const { return (m_signature == nullptr); } void invalidate(const bool); friend class Builder; friend class Widget; private: void paint(uint = 1); void aaPaint(); void colorise(); void setRingBreadth(); Chain *m_signature; QRect m_rect; uint m_ringBreadth; ///ring breadth uint m_innerRadius; ///radius of inner circle uint m_visibleDepth; ///visible level depth of system QString m_centerText; uint MAP_2MARGIN; }; class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget* = nullptr); QString path() const; QUrl url(File const * const = nullptr) const; bool isValid() const { return m_tree != nullptr; } friend struct Label; //FIXME badness public slots: void zoomIn(); void zoomOut(); void create(const Directory*); void invalidate(const bool = true); void refresh(int); private slots: void resizeTimeout(); void sendFakeMouseEvent(); void deleteJobFinished(KJob*); void createFromCache(const Directory*); signals: void activated(const QUrl&); void invalidated(const QUrl&); void created(const Directory*); void mouseHover(const QString&); protected: - void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE; - void resizeEvent(QResizeEvent*) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent*) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent*) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent*) override; + void resizeEvent(QResizeEvent*) override; + void mouseMoveEvent(QMouseEvent*) override; + void mousePressEvent(QMouseEvent*) override; protected: const Segment *segmentAt(QPoint&) const; //FIXME const reference for a library others can use const Segment *rootSegment() const { return m_rootSegment; } ///never == 0 const Segment *focusSegment() const { return m_focus; } ///0 == nothing in focus private: void paintExplodedLabels(QPainter&) const; const Directory *m_tree; const Segment *m_focus; QPoint m_offset; QTimer m_timer; Map m_map; SegmentTip m_tip; Segment *m_rootSegment; }; } #endif diff --git a/krusader/FileSystem/defaultfilesystem.h b/krusader/FileSystem/defaultfilesystem.h index 383e276e..2094c3c6 100644 --- a/krusader/FileSystem/defaultfilesystem.h +++ b/krusader/FileSystem/defaultfilesystem.h @@ -1,96 +1,96 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 DEFAULTFILESYSTEM_H #define DEFAULTFILESYSTEM_H #include "filesystem.h" #include #include /** * @brief Default filesystem implementation supporting all KIO protocols * * This filesystem implementation allows file operations and listing for all supported KIO protocols * (local and remote/network). * * Refreshing local directories is optimized for performance. * * NOTE: For detecting local file changes a filesystem watcher is used. It cannot be used for * refreshing the view after own file operations are performed because the detection is to slow * (~500ms delay between operation finished and watcher emits signals). * */ class DefaultFileSystem : public FileSystem { Q_OBJECT public: DefaultFileSystem(); void copyFiles(const QList &urls, const QUrl &destination, KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy, bool showProgressInfo = true, - JobMan::StartMode startMode = JobMan::Default) Q_DECL_OVERRIDE; - void dropFiles(const QUrl &destination, QDropEvent *event) Q_DECL_OVERRIDE; + JobMan::StartMode startMode = JobMan::Default) override; + void dropFiles(const QUrl &destination, QDropEvent *event) override; void addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, - const QString &dir = "") Q_DECL_OVERRIDE; - void mkDir(const QString &name) Q_DECL_OVERRIDE; - void rename(const QString &fileName, const QString &newName) Q_DECL_OVERRIDE; + const QString &dir = "") override; + void mkDir(const QString &name) override; + void rename(const QString &fileName, const QString &newName) override; /// Return URL for file name - even if file does not exist. - QUrl getUrl(const QString &name) const Q_DECL_OVERRIDE; - bool canMoveToTrash(const QStringList &) const Q_DECL_OVERRIDE { return isLocal(); } + QUrl getUrl(const QString &name) const override; + bool canMoveToTrash(const QStringList &) const override { return isLocal(); } - QString mountPoint() const Q_DECL_OVERRIDE { return _mountPoint; } - bool hasAutoUpdate() const Q_DECL_OVERRIDE { return !_watcher.isNull(); } - void updateFilesystemInfo() Q_DECL_OVERRIDE; + QString mountPoint() const override { return _mountPoint; } + bool hasAutoUpdate() const override { return !_watcher.isNull(); } + void updateFilesystemInfo() override; protected: - bool refreshInternal(const QUrl &origin, bool onlyScan) Q_DECL_OVERRIDE; + bool refreshInternal(const QUrl &origin, bool onlyScan) override; protected slots: /// Handle result after dir listing job is finished void slotListResult(KJob *job); /// Fill directory file list with new files from the dir lister void slotAddFiles(KIO::Job *job, const KIO::UDSEntryList &entries); /// URL redirection signal from dir lister void slotRedirection(KIO::Job *job, const QUrl &url); // React to filesystem changes nofified by watcher // NOTE: the path parameter can be the directory itself or files in this directory void slotWatcherCreated(const QString &path); void slotWatcherDirty(const QString &path); void slotWatcherDeleted(const QString &path); private: bool refreshLocal(const QUrl &directory, bool onlyScan); // NOTE: this is very fast FileItem *createLocalFileItem(const QString &name); /// Returns the current path with symbolic links resolved QString realPath(); static QUrl resolveRelativePath(const QUrl &url); QPointer _watcher; // dir watcher used to detect changes in the current dir bool _listError; // for async operation, return list job result QString _mountPoint; // the mount point of the current dir }; #endif diff --git a/krusader/FileSystem/filesystem.h b/krusader/FileSystem/filesystem.h index f76be1ad..90d44056 100644 --- a/krusader/FileSystem/filesystem.h +++ b/krusader/FileSystem/filesystem.h @@ -1,221 +1,221 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 FILESYSTEM_H #define FILESYSTEM_H #include "dirlisterinterface.h" // QtCore #include #include #include #include // QtGui #include // QtWidgets #include #include #include #include "../JobMan/jobman.h" class FileItem; /** * An abstract filesystem. Use the implementations of this class for all file operations. * * It represents a directory and gives access to its files. All common file operations * are supported. Methods with absolute URL as argument can be used independently from the current * directory. Otherwise - if the methods argument is a file name - the operation is performed inside * the current directory. * * Notification signals are emitted if the directory content may have been changed. */ class FileSystem : public DirListerInterface { Q_OBJECT public: enum FS_TYPE { /// Virtual filesystem. Krusaders custom virt:/ protocol FS_VIRTUAL, /// Filesystem supporting all KIO protocols (file:/, ftp:/, smb:/, etc.) FS_DEFAULT }; FileSystem(); ~FileSystem() override; // DirListerInterface implementation - inline QList fileItems() const Q_DECL_OVERRIDE { return _fileItems.values(); } - inline unsigned long numFileItems() const Q_DECL_OVERRIDE { return _fileItems.count(); } - inline bool isRoot() const Q_DECL_OVERRIDE { + inline QList fileItems() const override { return _fileItems.values(); } + inline unsigned long numFileItems() const override { return _fileItems.count(); } + inline bool isRoot() const override { const QString path = _currentDirectory.path(); return path.isEmpty() || path == "/"; } /// Copy (copy, move or link) files in this filesystem. /// Destination is absolute URL. May implemented async. virtual void copyFiles(const QList &urls, const QUrl &destination, KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy, bool showProgressInfo = true, JobMan::StartMode startMode = JobMan::Default) = 0; /// Handle file dropping in this filesystem. Destination is absolute URL. May implemented async. virtual void dropFiles(const QUrl &destination, QDropEvent *event) = 0; /// Copy (copy, move or link) files to the current filesystem directory or to "dir", the /// directory name relative to the current dir. May implemented async. virtual void addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, const QString &dir = "") = 0; /// Create a new directory in the current directory. May implemented async. virtual void mkDir(const QString &name) = 0; /// Rename file/directory in the current directory. May implemented async. virtual void rename(const QString &fileName, const QString &newName) = 0; /// Return an absolute URL for a single file/directory name in the current directory - with no /// trailing slash. virtual QUrl getUrl(const QString &name) const = 0; /// Return a list of URLs for multiple files/directories in the current directory. QList getUrls(const QStringList &names) const; /// Return true if all files can be moved to trash, else false. virtual bool canMoveToTrash(const QStringList &fileNames) const = 0; /// Return the filesystem mount point of the current directory. Empty string by default. virtual QString mountPoint() const { return QString(); } /// Returns true if this filesystem implementation does not need to be notified about changes in the /// current directory. Else false. virtual bool hasAutoUpdate() const { return false; } /// Notify this filesystem that the filesystem info of the current directory may have changed. virtual void updateFilesystemInfo() {} /** * Scan all files and directories in a directory and create the file items for them. Blocking. * * @param directory if given, the lister tries to change to this directory, else the old * directory is refreshed * @return true if scan was successful, else (not implemented, scan failed or refresh job * was killed) false. */ bool scanDir(const QUrl &directory = QUrl()) { return scanOrRefresh(directory, false); } /// Change or refresh the current directory and scan it. Blocking. /// Returns true if directory was scanned. Returns false if failed or scan job was killed. bool refresh(const QUrl &directory = QUrl()) { return scanOrRefresh(directory, false); } /// Returns the current directory path of this filesystem. inline QUrl currentDirectory() const { return _currentDirectory; } /// Return the file item for a file name in the current directory. Or 0 if not found. FileItem *getFileItem(const QString &name) const; /// The total size of all files in the current directory (only valid after scan). // TODO unused KIO::filesize_t totalSize() const; /// Return the filesystem type. inline FS_TYPE type() const { return _type; } /// Return true if the current directory is local (without recognizing mount points). inline bool isLocal() const { return _currentDirectory.isLocalFile(); } /// Return true if the current directory is a remote (network) location. inline bool isRemote() const { const QString sc = _currentDirectory.scheme(); return (sc == "fish" || sc == "ftp" || sc == "sftp" || sc == "nfs" || sc == "smb" || sc == "webdav"); } /// Returns true if this filesystem is currently refreshing the current directory. inline bool isRefreshing() const { return _isRefreshing; } /// Delete or trash arbitrary files. Implemented async. Universal refresh not fully implemented. void deleteFiles(const QList &urls, bool moveToTrash); /// Return the input URL with a trailing slash if absent. static QUrl ensureTrailingSlash(const QUrl &url); /// Return the input URL without trailing slash. static QUrl cleanUrl(const QUrl &url) { return url.adjusted(QUrl::StripTrailingSlash); } /// Add 'file' scheme to non-empty URL without scheme static QUrl preferLocalUrl(const QUrl &url); /// Return a file item for a local file inside a directory static FileItem *createLocalFileItem(const QString &name, const QString &directory, bool virt = false); /// Return a file item for a KIO result. Returns 0 if entry is not needed static FileItem *createFileItemFromKIO(const KIO::UDSEntry &entry, const QUrl &directory, bool virt = false); /// Read a symlink with an extra precaution static QString readLinkSafely(const char *path); /// Set the parent window to be used for dialogs void setParentWindow(QWidget *widget) { parentWindow = widget; } signals: /// Emitted when this filesystem is currently refreshing the filesystem directory. void refreshJobStarted(KIO::Job *job); /// Emitted when an error occurred in this filesystem during refresh. void error(const QString &msg); /// Emitted when the content of a directory was changed by this filesystem. void fileSystemChanged(const QUrl &directory, bool removed); /// Emitted when the information for the filesystem of the current directory changed. /// Information is either /// * 'metaInfo': a displayable string about the fs, empty by default, OR /// * 'fsType', 'total' and 'free': filesystem type, size and free space, /// empty string or 0 by default void fileSystemInfoChanged(const QString &metaInfo, const QString &fsType, KIO::filesize_t total, KIO::filesize_t free); /// Emitted before a directory path is opened for reading. Used for automounting. void aboutToOpenDir(const QString &path); protected: /// Fill the filesystem dictionary with file items, must be implemented for each filesystem. virtual bool refreshInternal(const QUrl &origin, bool stayInDir) = 0; /// Connect the result signal of a file operation job - source URLs. void connectJobToSources(KJob *job, const QList& urls); /// Connect the result signal of a file operation job - destination URL. void connectJobToDestination(KJob *job, const QUrl &destination); /// Returns true if showing hidden files is set in config. bool showHiddenFiles(); /// Add a new file item to the internal dictionary (while refreshing). void addFileItem(FileItem *item); FS_TYPE _type; // the filesystem type. QUrl _currentDirectory; // the path or file the filesystem originates from. bool _isRefreshing; // true if filesystem is busy with refreshing QPointer parentWindow; protected slots: /// Handle result after job (except when refreshing!) finished void slotJobResult(KJob *job, bool refresh); private: typedef QHash FileItemDict; // optional TODO: add an async version of this bool scanOrRefresh(const QUrl &directory, bool onlyScan); /// Delete and clear file items. void clear(FileItemDict &fileItems); FileItemDict _fileItems; // the list of files in the current dictionary }; #endif diff --git a/krusader/FileSystem/krquery.h b/krusader/FileSystem/krquery.h index 1f637cad..c2df7752 100644 --- a/krusader/FileSystem/krquery.h +++ b/krusader/FileSystem/krquery.h @@ -1,228 +1,228 @@ /***************************************************************************** * Copyright (C) 2001 Shie Erlich * * Copyright (C) 2001 Rafi Yanai * * Copyright (C) 2004-2019 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 KRQUERY_H #define KRQUERY_H // QtCore #include #include #include #include #include class QTextCodec; class FileItem; /** * @brief A search query for files * * Can be used for finding or selecting files and folders by multiple limiting search criteria */ class KRQuery : public QObject { Q_OBJECT public: // null query KRQuery(); // query only with name filter explicit KRQuery(const QString &name, bool matchCase = true); // copy constructor KRQuery(const KRQuery &); // let operator KRQuery &operator=(const KRQuery &); // destructor ~KRQuery() override; // load parameters from config void load(const KConfigGroup& cfg); // save parameters to config void save(KConfigGroup cfg); // matching a file with the query bool match(FileItem *file) const; // checks if the given fileItem object matches the conditions // matching a name with the query bool match(const QString &name) const; // matching the filename only // matching the name of the directory bool matchDirName(const QString &name) const; // sets the text for name filtering void setNameFilter(const QString &text, bool cs = true); // returns the current filter mask const QString &nameFilter() const { return origFilter; } // returns whether the filter is case sensitive bool isCaseSensitive() { return matchesCaseSensitive; } // returns if the filter is null (was cancelled) bool isNull() { return bNull; } // sets the content part of the query void setContent(const QString &content, bool cs = true, bool wholeWord = false, const QString& encoding = QString(), bool regExp = false); const QString content() { return contain; } // sets the minimum file size limit void setMinimumFileSize(KIO::filesize_t); // sets the maximum file size limit void setMaximumFileSize(KIO::filesize_t); // sets the time the file newer than void setNewerThan(time_t time); // sets the time the file older than void setOlderThan(time_t time); // sets the owner void setOwner(const QString &ownerIn); // sets the group void setGroup(const QString &groupIn); // sets the permissions void setPermissions(const QString &permIn); // sets the mimetype for the query // type, must be one of the following: // 1. a valid mime type name // 2. one of: i18n("Archives"), i18n("Folders"), i18n("Image Files") // i18n("Text Files"), i18n("Video Files"), i18n("Audio Files") // 3. i18n("Custom") in which case you must supply a list of valid mime-types // in the member QStringList customType void setMimeType(const QString &typeIn, QStringList customList = QStringList()); // true if setMimeType was called bool hasMimeType() { return type.isEmpty(); } // sets the search in archive flag void setSearchInArchives(bool flag) { inArchive = flag; } // gets the search in archive flag bool searchInArchives() { return inArchive; } // sets the recursive flag void setRecursive(bool flag) { recurse = flag; } // gets the recursive flag bool isRecursive() { return recurse; } // sets whether to follow symbolic links void setFollowLinks(bool flag) { followLinksP = flag; } // gets whether to follow symbolic links bool followLinks() { return followLinksP; } // sets the folder names which the searcher will exclude from traversing void setExcludeFolderNames(const QStringList &urls); // gets the folder names which the searcher excludes const QStringList excludeFolderNames() { return excludedFolderNames; } // sets the folders where the searcher will search void setSearchInDirs(const QList &urls); // gets the folders where the searcher searches const QList &searchInDirs() { return whereToSearch; } // sets the folders where search is not permitted void setDontSearchInDirs(const QList &urls); // gets the folders where search is not permitted const QList &dontSearchInDirs() { return whereNotToSearch; } // checks if a URL is excluded bool isExcluded(const QUrl &url); // gives whether we search for content bool isContentSearched() const { return !contain.isEmpty(); } bool checkLine(const QString &line, bool backwards = false) const; const QString &foundText() const { return lastSuccessfulGrep; } int matchIndex() const { return lastSuccessfulGrepMatchIndex; } int matchLength() const { return lastSuccessfulGrepMatchLength; } protected: // important to know whether the event processor is connected - void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; + void connectNotify(const QMetaMethod &signal) override; // important to know whether the event processor is connected - void disconnectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; + void disconnectNotify(const QMetaMethod &signal) override; protected: QStringList matches; // what to search QStringList excludes; // what to exclude QStringList includedDirs; // what dirs to include QStringList excludedDirs; // what dirs to exclude bool matchesCaseSensitive; bool bNull; // flag if the query is null QString contain; // file must contain this string bool containCaseSensetive; bool containWholeWord; bool containRegExp; KIO::filesize_t minSize; KIO::filesize_t maxSize; time_t newerThen; time_t olderThen; QString owner; QString group; QString perm; QString type; QStringList customType; bool inArchive; // if true- search in archive. bool recurse; // if true recurse ob sub-dirs... bool followLinksP; QStringList excludedFolderNames; // substrings of paths where not to search QList whereToSearch; // directories to search QList whereNotToSearch; // directories NOT to search signals: void status(const QString &name); void processEvents(bool &stopped); private: bool matchCommon(const QString &, const QStringList &, const QStringList &) const; bool checkPerm(QString perm) const; bool checkType(const QString& mime) const; bool containsContent(const QString& file) const; bool containsContent(const QUrl& url) const; bool checkBuffer(const char *data, int len) const; bool checkTimer() const; QStringList split(QString); private slots: void containsContentData(KIO::Job *, const QByteArray &); void containsContentFinished(KJob *); private: QString origFilter; mutable bool busy; mutable bool containsContentResult; mutable char *receivedBuffer; mutable int receivedBufferLen; mutable QString lastSuccessfulGrep; mutable int lastSuccessfulGrepMatchIndex; mutable int lastSuccessfulGrepMatchLength; mutable QString fileName; mutable KIO::filesize_t receivedBytes; mutable KIO::filesize_t totalBytes; mutable int processEventsConnected; mutable QTime timer; QTextCodec *codec; const char *encodedEnter; int encodedEnterLen; QByteArray encodedEnterArray; }; #endif diff --git a/krusader/FileSystem/virtualfilesystem.h b/krusader/FileSystem/virtualfilesystem.h index bbf5265c..41ab2b59 100644 --- a/krusader/FileSystem/virtualfilesystem.h +++ b/krusader/FileSystem/virtualfilesystem.h @@ -1,107 +1,107 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * Copyright (C) 2004-2019 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 VIRTUALFILESYSTEM_H #define VIRTUALFILESYSTEM_H // QtCore #include #include #include "filesystem.h" /** * Custom virtual filesystem implementation: It holds arbitrary lists of files which are only * virtual references to real files. The filename of a virtual file is the full path of the real * file. * * Only two filesystem levels are supported: On root level only directories can be created; these * virtual root directories can contain a set of virtual files and directories. Entering a directory * on the sublevel is out of scope and the real directory will be opened. * * The filesystem content is saved in a separate config file and preserved between application runs. * * Used at least by bookmarks, locate, search and synchronizer dialog. */ class VirtualFileSystem : public FileSystem { Q_OBJECT public: VirtualFileSystem(); /// Create virtual files in this filesystem. Copy mode and showProgressInfo are ignored. void copyFiles(const QList &urls, const QUrl &destination, KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy, bool showProgressInfo = false, - JobMan::StartMode startMode = JobMan::Start) Q_DECL_OVERRIDE; + JobMan::StartMode startMode = JobMan::Start) override; /// Handle file dropping in this filesystem: Always creates virtual files. - void dropFiles(const QUrl &destination, QDropEvent *event) Q_DECL_OVERRIDE; + void dropFiles(const QUrl &destination, QDropEvent *event) override; /// Add virtual files to the current directory. void addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy, - const QString &dir = "") Q_DECL_OVERRIDE; + const QString &dir = "") override; /// Create a virtual directory. Only possible in the root directory. - void mkDir(const QString &name) Q_DECL_OVERRIDE; + void mkDir(const QString &name) override; /// Rename a (real) file in the current directory. - void rename(const QString &fileName, const QString &newName) Q_DECL_OVERRIDE; + void rename(const QString &fileName, const QString &newName) override; /// Returns the URL of the real file or an empty URL if file with name does not exist. - QUrl getUrl(const QString& name) const Q_DECL_OVERRIDE; - bool canMoveToTrash(const QStringList &fileNames) const Q_DECL_OVERRIDE; + QUrl getUrl(const QString& name) const override; + bool canMoveToTrash(const QStringList &fileNames) const override; /// Remove virtual files or directories. Real files stay untouched. void remove(const QStringList &fileNames); /// Set meta information to be displayed in UI for the current directory void setMetaInformation(const QString &info); protected: - bool refreshInternal(const QUrl &origin, bool onlyScan) Q_DECL_OVERRIDE; + bool refreshInternal(const QUrl &origin, bool onlyScan) override; private: /// Return current dir: "/" or pure directory name inline QString currentDir() { const QString path = _currentDirectory.path().mid(1); // remove slash return path.isEmpty() ? "/" : path; } void mkDirInternal(const QString& name); /// Save the dictionary to file void save(); /// Restore the dictionary from file void restore(); /// Create local or KIO fileItem. Returns 0 if file does not exist FileItem *createFileItem(const QUrl &url); /// Return the configuration file storing the urls of virtual files KConfig &getVirtDB(); private slots: void slotStatResult(KJob *job); private: void showError(const QString &error); static QHash *> _virtFilesystemDict; // map virtual directories to containing files static QHash _metaInfoDict; // map virtual directories to meta info QString _metaInfo; // displayable string with information about the current virtual directory KIO::UDSEntry _fileEntry; // for async call, save stat job result here }; #endif diff --git a/krusader/Filter/advancedfilter.h b/krusader/Filter/advancedfilter.h index ae30647a..e3a9a85f 100644 --- a/krusader/Filter/advancedfilter.h +++ b/krusader/Filter/advancedfilter.h @@ -1,120 +1,120 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * Copyright (C) 2003 Csaba Karai * * Copyright (C) 2004-2019 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 ADVANCEDFILTER_H #define ADVANCEDFILTER_H #include "filterbase.h" // QtWidgets #include #include #include #include #include #include class QSpinBox; class AdvancedFilter : public QWidget, public FilterBase { Q_OBJECT public: explicit AdvancedFilter(FilterTabs *tabs, QWidget *parent = nullptr); - void queryAccepted() Q_DECL_OVERRIDE {} - QString name() Q_DECL_OVERRIDE { + void queryAccepted() override {} + QString name() override { return "AdvancedFilter"; } - FilterTabs * filterTabs() Q_DECL_OVERRIDE { + FilterTabs * filterTabs() override { return fltTabs; } - bool getSettings(FilterSettings&) Q_DECL_OVERRIDE; - void applySettings(const FilterSettings&) Q_DECL_OVERRIDE; + bool getSettings(FilterSettings&) override; + void applySettings(const FilterSettings&) override; public slots: void modifiedBetweenSetDate1(); void modifiedBetweenSetDate2(); void notModifiedAfterSetDate(); public: QCheckBox* minSizeEnabled; QSpinBox* minSizeAmount; KComboBox* minSizeType; QCheckBox* maxSizeEnabled; QSpinBox* maxSizeAmount; KComboBox* maxSizeType; QRadioButton* anyDateEnabled; QRadioButton* modifiedBetweenEnabled; QRadioButton* notModifiedAfterEnabled; QRadioButton* modifiedInTheLastEnabled; KLineEdit* modifiedBetweenData1; KLineEdit* modifiedBetweenData2; QToolButton* modifiedBetweenBtn1; QToolButton* modifiedBetweenBtn2; QToolButton* notModifiedAfterBtn; KLineEdit* notModifiedAfterData; QSpinBox* modifiedInTheLastData; QSpinBox* notModifiedInTheLastData; KComboBox* modifiedInTheLastType; KComboBox* notModifiedInTheLastType; QCheckBox* belongsToUserEnabled; KComboBox* belongsToUserData; QCheckBox* belongsToGroupEnabled; KComboBox* belongsToGroupData; QCheckBox* permissionsEnabled; KComboBox* ownerW; KComboBox* ownerR; KComboBox* ownerX; KComboBox* groupW; KComboBox* groupR; KComboBox* groupX; KComboBox* allW; KComboBox* allX; KComboBox* allR; FilterTabs *fltTabs; private: void changeDate(KLineEdit *p); void fillList(KComboBox *list, const QString& filename); void invalidDateMessage(KLineEdit *p); static QDate stringToDate(const QString& text) { // 30.12.16 is interpreted as 1916-12-30 return QLocale().toDate(text, QLocale::ShortFormat).addYears(100); } static QString dateToString(const QDate& date) { return QLocale().toString(date, QLocale::ShortFormat); } }; #endif /* ADVANCEDFILTER_H */ diff --git a/krusader/Filter/generalfilter.h b/krusader/Filter/generalfilter.h index 83fa26b7..9da4c299 100644 --- a/krusader/Filter/generalfilter.h +++ b/krusader/Filter/generalfilter.h @@ -1,119 +1,119 @@ /***************************************************************************** * Copyright (C) 2003 Csaba Karai * * Copyright (C) 2004-2019 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 GENERALFILTER_H #define GENERALFILTER_H // QtWidgets #include #include #include #include #include #include #include #include #include #include "filterbase.h" #include "../Dialogs/kurllistrequester.h" #include "../GUI/profilemanager.h" #include "../GUI/krlistwidget.h" #include "../GUI/krhistorycombobox.h" class GeneralFilter : public QWidget, public FilterBase { Q_OBJECT public: GeneralFilter(FilterTabs *tabs, int properties, QWidget *parent = nullptr, QStringList extraOptions = QStringList()); ~GeneralFilter() override; - void queryAccepted() Q_DECL_OVERRIDE; - QString name() Q_DECL_OVERRIDE { + void queryAccepted() override; + QString name() override { return "GeneralFilter"; } - FilterTabs * filterTabs() Q_DECL_OVERRIDE { + FilterTabs * filterTabs() override { return fltTabs; } - bool getSettings(FilterSettings&) Q_DECL_OVERRIDE; - void applySettings(const FilterSettings&) Q_DECL_OVERRIDE; + bool getSettings(FilterSettings&) override; + void applySettings(const FilterSettings&) override; bool isExtraOptionChecked(const QString& name); void checkExtraOption(const QString& name, bool check); public slots: void slotAddBtnClicked(); void slotLoadBtnClicked(); void slotOverwriteBtnClicked(); void slotRemoveBtnClicked(); void slotDisable(); void slotRegExpTriggered(QAction * act); void slotProfileDoubleClicked(QListWidgetItem *); void refreshProfileListBox(); public: KComboBox* contentEncoding; QCheckBox* searchForCase; QCheckBox* containsTextCase; QCheckBox* containsWholeWord; QCheckBox* useExcludeFolderNames; QCheckBox* searchInDirs; QCheckBox* searchInArchives; QCheckBox* followLinks; QHash extraOptions; KURLListRequester *searchIn; KURLListRequester *dontSearchIn; QLayout *middleLayout; KrHistoryComboBox* searchFor; KHistoryComboBox* containsText; KHistoryComboBox* excludeFolderNames; QToolButton* containsRegExp; KComboBox* ofType; QLabel *encLabel; QLabel *containsLabel; KShellCompletion completion; KrListWidget *profileListBox; QPushButton *profileAddBtn; QPushButton *profileLoadBtn; QPushButton *profileOverwriteBtn; QPushButton *profileRemoveBtn; ProfileManager *profileManager; int properties; FilterTabs *fltTabs; private: QCheckBox *createExcludeCheckBox(const KConfigGroup &group); KHistoryComboBox *createExcludeComboBox(const KConfigGroup &group); }; #endif /* GENERALFILTER_H */ diff --git a/krusader/GUI/kcmdline.h b/krusader/GUI/kcmdline.h index e72b1a16..e2c13379 100644 --- a/krusader/GUI/kcmdline.h +++ b/krusader/GUI/kcmdline.h @@ -1,119 +1,119 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KCMDLINE_H #define KCMDLINE_H // QtGui #include // QtWidgets #include #include #include #include #include #include #include #include "../UserAction/kractionbase.h" class KCMDModeButton; class CmdLineCombo : public KHistoryComboBox { Q_OBJECT public: explicit CmdLineCombo(QWidget *parent); - bool eventFilter(QObject *watched, QEvent *e) Q_DECL_OVERRIDE; + bool eventFilter(QObject *watched, QEvent *e) override; QString path() { return _path; } void setPath(QString path); signals: void returnToPanel(); protected slots: void doLayout(); protected: - void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *e) override; + void keyPressEvent(QKeyEvent *e) override; void updateLineEditGeometry(); QLabel *_pathLabel; QString _path; bool _handlingLineEditResize; }; class KCMDLine : public QWidget, KrActionBase { Q_OBJECT public: explicit KCMDLine(QWidget *parent = nullptr); ~KCMDLine() override; void setCurrent(const QString &path); //virtual methods from KrActionBase void setText(const QString& text); - QString command() const Q_DECL_OVERRIDE; - ExecType execType() const Q_DECL_OVERRIDE; - QString startpath() const Q_DECL_OVERRIDE; - QString user() const Q_DECL_OVERRIDE; - QString text() const Q_DECL_OVERRIDE; - bool acceptURLs() const Q_DECL_OVERRIDE; - bool confirmExecution() const Q_DECL_OVERRIDE; - bool doSubstitution() const Q_DECL_OVERRIDE; + QString command() const override; + ExecType execType() const override; + QString startpath() const override; + QString user() const override; + QString text() const override; + bool acceptURLs() const override; + bool confirmExecution() const override; + bool doSubstitution() const override; signals: void signalRun(); public slots: void slotReturnFocus(); // returns keyboard focus to panel void slotRun(); void addPlaceholder(); void addText(const QString& text) { cmdLine->lineEdit()->setText(cmdLine->lineEdit()->text() + text); } void popup() { cmdLine->showPopup(); } protected: - void focusInEvent(QFocusEvent*) Q_DECL_OVERRIDE { + void focusInEvent(QFocusEvent*) override { cmdLine->setFocus(); } void calcLabelSize(); private: CmdLineCombo *cmdLine; KCMDModeButton *terminal; QToolButton *buttonAddPlaceholder; KShellCompletion completion; }; #endif diff --git a/krusader/GUI/krstyleproxy.h b/krusader/GUI/krstyleproxy.h index 70a8b8f9..6b8107b0 100644 --- a/krusader/GUI/krstyleproxy.h +++ b/krusader/GUI/krstyleproxy.h @@ -1,39 +1,39 @@ /***************************************************************************** * Copyright (C) 2008 Csaba Karai * * Copyright (C) 2008-2019 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 KRSTYLEPROXY_H #define KRSTYLEPROXY_H // QtWidgets #include class KrStyleProxy: public QProxyStyle { public: void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, - const QWidget *widget = 0) const Q_DECL_OVERRIDE; + const QWidget *widget = 0) const override; int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, - QStyleHintReturn *returnData) const Q_DECL_OVERRIDE; + QStyleHintReturn *returnData) const override; }; #endif /* KRSTYLEPROXY_H */ diff --git a/krusader/GUI/krtreewidget.h b/krusader/GUI/krtreewidget.h index 3ac4f371..c51fb4f6 100644 --- a/krusader/GUI/krtreewidget.h +++ b/krusader/GUI/krtreewidget.h @@ -1,56 +1,56 @@ /***************************************************************************** * Copyright (C) 2008 Csaba Karai * * Copyright (C) 2008-2019 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 KRTREEWIDGET_H #define KRTREEWIDGET_H // QtWidgets #include #include class KrTreeWidget : public QTreeWidget { Q_OBJECT public: explicit KrTreeWidget(QWidget * parent); void setStretchingColumn(int col) { _stretchingColumn = col; } QModelIndex indexOf(QTreeWidgetItem * item, int col = 0) { return indexFromItem(item, col); } QTreeWidgetItem * item(const QModelIndex & ndx) { return itemFromIndex(ndx); } signals: void itemRightClicked(QTreeWidgetItem * it, const QPoint & pos, int column); protected: - bool event(QEvent * event) Q_DECL_OVERRIDE; + bool event(QEvent * event) override; private: int _stretchingColumn; bool _inResize; }; #endif /* KRTREEWIDGET_H */ diff --git a/krusader/GUI/mediabutton.h b/krusader/GUI/mediabutton.h index d095bc41..bfe064f9 100644 --- a/krusader/GUI/mediabutton.h +++ b/krusader/GUI/mediabutton.h @@ -1,93 +1,93 @@ /***************************************************************************** * Copyright (C) 2006 Csaba Karai * * Copyright (C) 2006-2019 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 MEDIABUTTON_H #define MEDIABUTTON_H // QtCore #include #include #include #include #include // QtWidgets #include #include #include #include #include class QMenu; class MediaButton : public QToolButton { Q_OBJECT public: explicit MediaButton(QWidget *parent = nullptr); ~MediaButton() override; public slots: void slotAboutToShow(); void slotAboutToHide(); void slotPopupActivated(QAction *); void slotAccessibilityChanged(bool, const QString &); void slotDeviceAdded(const QString&); void slotDeviceRemoved(const QString&); void showMenu(); void slotCheckMounts(); void updateIcon(const QString &mountPoint); signals: void openUrl(const QUrl&); void newTab(const QUrl&); void aboutToShow(); protected: - bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE; + bool eventFilter(QObject *o, QEvent *e) override; bool getNameAndIcon(Solid::Device &, QString &, QIcon &); private: void createMediaList(); void toggleMount(const QString& udi); void getStatus(const QString& udi, bool &mounted, QString *mountPointOut = nullptr, bool *ejectableOut = nullptr); void mount(const QString&, bool open = false, bool newtab = false); void umount(const QString&); void eject(QString); void rightClickMenu(const QString& udi, QPoint pos); QList storageDevices; private slots: void slotSetupDone(Solid::ErrorType error, const QVariant& errorData, const QString &udi); private: static QString remotePrefix; QMenu *popupMenu; QMenu *rightMenu; QString udiToOpen; bool openInNewTab; QMap udiNameMap; QTimer mountCheckerTimer; QString currentMountPoint; // for performance optimization }; #endif /* MEDIABUTTON_H */ diff --git a/krusader/GUI/terminaldock.h b/krusader/GUI/terminaldock.h index 04c6ed51..d481b590 100644 --- a/krusader/GUI/terminaldock.h +++ b/krusader/GUI/terminaldock.h @@ -1,74 +1,74 @@ /***************************************************************************** * Copyright (C) 2008 Václav Juza * * Copyright (C) 2008-2019 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 TERMINALDOCK_H #define TERMINALDOCK_H // QtCore #include #include #include // QtWidgets #include #include #include #include class KrMainWindow; /** * This is a class to make the work with the embedded terminal emulator easier. * It takes care of loading the library and initialising when necessary. * A big advantage is that the code which uses this class does not need to * check if the part was loaded successfully. * */ class TerminalDock : public QWidget { Q_OBJECT public: TerminalDock(QWidget* parent, KrMainWindow *mainWindow); ~TerminalDock() override; void sendInput(const QString& input, bool clearCommand=true); void sendCd(const QString& path); - bool eventFilter(QObject * watched, QEvent * e) Q_DECL_OVERRIDE; + bool eventFilter(QObject * watched, QEvent * e) override; bool isTerminalVisible() const; bool isInitialised() const; bool initialise(); - void hideEvent(QHideEvent * e) Q_DECL_OVERRIDE; - void showEvent(QShowEvent * e) Q_DECL_OVERRIDE; + void hideEvent(QHideEvent * e) override; + void showEvent(QShowEvent * e) override; inline KParts::Part* part() { return konsole_part; } private slots: void killTerminalEmulator(); private: KrMainWindow *_mainWindow; QString lastPath; // path of the last sendCd QHBoxLayout *terminal_hbox; // hbox for terminal_dock KParts::ReadOnlyPart* konsole_part; // the actual part pointer TerminalInterface* t; // TerminalInterface of the konsole part bool initialised; bool firstInput; bool applyShortcuts(QKeyEvent * ke); }; #endif /* TERMINALDOCK_H */ diff --git a/krusader/KViewer/krviewer.h b/krusader/KViewer/krviewer.h index 2eaf80f8..5afc35e0 100644 --- a/krusader/KViewer/krviewer.h +++ b/krusader/KViewer/krviewer.h @@ -1,154 +1,154 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 KRVIEWER_H #define KRVIEWER_H // QtCore #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include "../krglobal.h" class PanelViewerBase; class KrViewer : public KParts::MainWindow { Q_OBJECT public: virtual ~KrViewer(); enum Mode {Generic, Text, Hex, Lister, Default}; static void view(QUrl url, QWidget * parent = krMainWindow); static void view(QUrl url, Mode mode, bool new_window, QWidget * parent = krMainWindow); static void edit(QUrl url, QWidget * parent); static void edit(const QUrl& url, Mode mode = Text, int new_window = -1, QWidget * parent = krMainWindow); static void configureDeps(); - virtual bool eventFilter(QObject * watched, QEvent * e) Q_DECL_OVERRIDE; + virtual bool eventFilter(QObject * watched, QEvent * e) override; public slots: void createGUI(KParts::Part*); void configureShortcuts(); void viewGeneric(); void viewText(); void viewHex(); void viewLister(); void editText(); void print(); void copy(); void tabChanged(int index); void tabURLChanged(PanelViewerBase * pvb, const QUrl &url); void tabCloseRequest(int index, bool force = false); void tabCloseRequest(); void nextTab(); void prevTab(); void detachTab(); void checkModified(); protected: - virtual bool queryClose() Q_DECL_OVERRIDE; - virtual void changeEvent(QEvent *e) Q_DECL_OVERRIDE; - virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; - virtual void focusInEvent(QFocusEvent *) Q_DECL_OVERRIDE { + virtual bool queryClose() override; + virtual void changeEvent(QEvent *e) override; + virtual void resizeEvent(QResizeEvent *e) override; + virtual void focusInEvent(QFocusEvent *) override { if (viewers.removeAll(this)) viewers.prepend(this); } // move to first private slots: void openUrlFinished(PanelViewerBase *pvb, bool success); private: explicit KrViewer(QWidget *parent = 0); void addTab(PanelViewerBase* pvb); void updateActions(); void refreshTab(PanelViewerBase* pvb); void viewInternal(QUrl url, Mode mode, QWidget * parent = krMainWindow); void editInternal(QUrl url, Mode mode, QWidget * parent = krMainWindow); void addPart(KParts::ReadOnlyPart *part); void removePart(KParts::ReadOnlyPart *part); bool isPartAdded(KParts::Part* part); static KrViewer* getViewer(bool new_window); static QString makeTabText(PanelViewerBase *pvb); static QString makeTabToolTip(PanelViewerBase *pvb); static QIcon makeTabIcon(PanelViewerBase *pvb); KParts::PartManager manager; QMenu* viewerMenu; QTabWidget tabBar; QPointer returnFocusTo; QAction *detachAction; QAction *printAction; QAction *copyAction; QAction *quitAction; QAction *configKeysAction; QAction *tabCloseAction; QAction *tabNextAction; QAction *tabPrevAction; static QList viewers; // the first viewer is the active one QList reservedKeys; // the reserved key sequences QList reservedKeyActions; // the IDs of the reserved keys int sizeX; int sizeY; }; class Invoker : public QObject { Q_OBJECT public: Invoker(QObject *recv, const char * slot) { connect(this, SIGNAL(invokeSignal()), recv, slot); } void invoke() { emit invokeSignal(); } signals: void invokeSignal(); }; #endif diff --git a/krusader/KViewer/lister.cpp b/krusader/KViewer/lister.cpp index b3e6038a..ba162e08 100644 --- a/krusader/KViewer/lister.cpp +++ b/krusader/KViewer/lister.cpp @@ -1,2277 +1,2277 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * Copyright (C) 2009-2019 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" #include "../compat.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.QFONTMETRICS_WIDTH("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW") - fm.QFONTMETRICS_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) { auto *ke = dynamic_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: - QString currentCharacterSet() Q_DECL_OVERRIDE { + QString currentCharacterSet() override { return _lister->characterSet(); } - void chooseDefault() Q_DECL_OVERRIDE { + void chooseDefault() override { _lister->setCharacterSet(QString()); } - void chooseEncoding(QString encodingName) Q_DECL_OVERRIDE { + void chooseEncoding(QString encodingName) 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); auto *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); auto *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")); auto * 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, &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? */ auto *kioJob = dynamic_cast(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(nullptr); 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, &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, &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 auto 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::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.QFONTMETRICS_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); auto 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 ff6dd70e..6fad0530 100644 --- a/krusader/KViewer/lister.h +++ b/krusader/KViewer/lister.h @@ -1,320 +1,320 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * Copyright (C) 2009-2019 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: - void resizeEvent(QResizeEvent * event) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent * e) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent * e) Q_DECL_OVERRIDE; - void mouseDoubleClickEvent(QMouseEvent * e) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent * e) Q_DECL_OVERRIDE; - void wheelEvent(QWheelEvent * event) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent * event) override; + void keyPressEvent(QKeyEvent * e) override; + void mousePressEvent(QMouseEvent * e) override; + void mouseDoubleClickEvent(QMouseEvent * e) override; + void mouseMoveEvent(QMouseEvent * e) override; + void wheelEvent(QWheelEvent * event) override; QStringList readLines(const qint64 filePos, qint64 &endPos, const int lines, QList * locs = nullptr); 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); 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: - bool event(QEvent *event) Q_DECL_OVERRIDE; + bool event(QEvent *event) 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: - bool openUrl(const QUrl &url) Q_DECL_OVERRIDE; - bool closeUrl() Q_DECL_OVERRIDE { + bool openUrl(const QUrl &url) override; + bool closeUrl() override { return true; } - bool openFile() Q_DECL_OVERRIDE { + bool openFile() override { return true; } - void guiActivateEvent(KParts::GUIActivateEvent * event) Q_DECL_OVERRIDE; + void guiActivateEvent(KParts::GUIActivateEvent * event) 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 = nullptr; bool _downloading = false; bool _restartFromBeginning = false; QTimer _downloadUpdateTimer; qint64 _savePosition = 0; qint64 _saveEnd = 0; }; #endif // __LISTER_H__ diff --git a/krusader/KViewer/panelviewer.h b/krusader/KViewer/panelviewer.h index 60fb229d..1288cac6 100644 --- a/krusader/KViewer/panelviewer.h +++ b/krusader/KViewer/panelviewer.h @@ -1,140 +1,140 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 PANELVIEWER_H #define PANELVIEWER_H // QtCore #include #include #include // QtWidgets #include #include # include #include "krviewer.h" class PanelViewerBase: public QStackedWidget { Q_OBJECT public: explicit PanelViewerBase(QWidget *parent, KrViewer::Mode mode = KrViewer::Default); ~PanelViewerBase() override; inline QUrl url() const { return curl; } inline KParts::ReadOnlyPart* part() const { return cpart; } virtual bool isModified() { return false; } virtual bool isEditor() = 0; public slots: virtual bool closeUrl() { return false; } virtual bool queryClose() { return true; } void openUrl(const QUrl& url); signals: void openUrlRequest(const QUrl &url); void urlChanged(PanelViewerBase *, const QUrl &); void partDestroyed(PanelViewerBase *); void openUrlFinished(PanelViewerBase *viewWidget, bool success); protected slots: void slotCPartDestroyed() { emit partDestroyed(this); } void slotStatResult(KJob* job); protected: virtual void openFile(KFileItem fi) = 0; virtual KParts::ReadOnlyPart* createPart(QString mimetype) = 0; KParts::ReadOnlyPart* getPart(const QString& mimetype); QHash > *mimes; QPointer cpart; QUrl curl; QLabel *fallback; KrViewer::Mode mode; }; class PanelViewer: public PanelViewerBase { Q_OBJECT public slots: - bool closeUrl() Q_DECL_OVERRIDE; + bool closeUrl() override; public: explicit PanelViewer(QWidget *parent, KrViewer::Mode mode = KrViewer::Default); ~PanelViewer() override; - bool isEditor() Q_DECL_OVERRIDE { + bool isEditor() override { return false; } protected: - void openFile(KFileItem fi) Q_DECL_OVERRIDE; - KParts::ReadOnlyPart* createPart(QString mimetype) Q_DECL_OVERRIDE; + void openFile(KFileItem fi) override; + KParts::ReadOnlyPart* createPart(QString mimetype) override; KParts::ReadOnlyPart* getDefaultPart(const KFileItem& fi); KParts::ReadOnlyPart* getHexPart(); KParts::ReadOnlyPart* getListerPart(bool hexMode = false); KParts::ReadOnlyPart* getTextPart(); }; class PanelEditor: public PanelViewerBase { Q_OBJECT public: - bool isModified() Q_DECL_OVERRIDE; - bool isEditor() Q_DECL_OVERRIDE { + bool isModified() override; + bool isEditor() override { return true; } static void configureDeps(); public slots: - bool closeUrl() Q_DECL_OVERRIDE; - bool queryClose() Q_DECL_OVERRIDE; + bool closeUrl() override; + bool queryClose() override; public: explicit PanelEditor(QWidget *parent, KrViewer::Mode mode = KrViewer::Default); ~PanelEditor() override; protected: - void openFile(KFileItem fi) Q_DECL_OVERRIDE; - KParts::ReadOnlyPart* createPart(QString mimetype) Q_DECL_OVERRIDE; + void openFile(KFileItem fi) override; + KParts::ReadOnlyPart* createPart(QString mimetype) override; static QString missingKPartMsg(); }; #endif diff --git a/krusader/Konfigurator/kgcolors.h b/krusader/Konfigurator/kgcolors.h index f72cbc04..f517f838 100644 --- a/krusader/Konfigurator/kgcolors.h +++ b/krusader/Konfigurator/kgcolors.h @@ -1,141 +1,141 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 KGCOLORS_H #define KGCOLORS_H // QtCore #include // QtWidgets #include #include #include #include #include "konfiguratorpage.h" #include "../GUI/krtreewidget.h" class KgColors : public KonfiguratorPage { Q_OBJECT public: explicit KgColors(bool first, QWidget* parent = nullptr); - bool apply() Q_DECL_OVERRIDE; + bool apply() override; public slots: void slotDisable(); void slotForegroundChanged(); void slotBackgroundChanged(); void slotAltBackgroundChanged(); void slotActiveChanged(); void slotMarkedBackgroundChanged(); void slotInactiveForegroundChanged(); void slotInactiveBackgroundChanged(); void slotInactiveAltBackgroundChanged(); void slotInactiveMarkedBackgroundChanged(); void generatePreview(); protected slots: void slotImportColors(); void slotExportColors(); private: class PreviewItem; int addColorSelector(const QString& cfgName, QString name, QColor defaultValue, const QString& dfltName = QString(), ADDITIONAL_COLOR *addColor = nullptr, int addColNum = 0); KonfiguratorColorChooser *getColorSelector(const QString& name); QLabel *getSelectorLabel(const QString& name); void serialize(class QDataStream &); void deserialize(class QDataStream &); void serializeItem(class QDataStream &, const char * name); void setColorWithDimming(PreviewItem * item, QColor foreground, QColor background, bool dimmed); private: QWidget *colorsGrp; QGridLayout *colorsGrid; int offset; int endOfActiveColors; int endOfPanelColors; int activeTabIdx, inactiveTabIdx; #ifdef SYNCHRONIZER_ENABLED int synchronizerTabIdx; #endif int otherTabIdx; QGroupBox *previewGrp; QGridLayout *previewGrid; QTabWidget *colorTabWidget; QStackedWidget *inactiveColorStack; QWidget *normalInactiveWidget; QWidget *dimmedInactiveWidget; KonfiguratorSpinBox *dimFactor; KonfiguratorCheckBoxGroup *generals; QList labelList; QList itemList; QList itemNames; KrTreeWidget *preview; QPushButton *importBtn, *exportBtn; class PreviewItem : public QTreeWidgetItem { private: QColor defaultBackground; QColor defaultForeground; QString label; public: PreviewItem(QTreeWidget * parent, const QString& name) { setText(0, name); defaultBackground = QColor(255, 255, 255); defaultForeground = QColor(0, 0, 0); label = name; parent->insertTopLevelItem(0, this); } void setColor(const QColor& foregnd, const QColor& backgnd) { defaultForeground = foregnd; defaultBackground = backgnd; QBrush textColor(foregnd); QBrush baseColor(backgnd); for (int i = 0; i != columnCount(); i++) { if (backgnd.isValid()) setBackground(i, baseColor); if (foregnd.isValid()) setForeground(i, textColor); } } QString text() { return label; } }; }; #endif /* __KGCOLORS_H__ */ diff --git a/krusader/Konfigurator/kgdependencies.h b/krusader/Konfigurator/kgdependencies.h index 1670a63a..f7654227 100644 --- a/krusader/Konfigurator/kgdependencies.h +++ b/krusader/Konfigurator/kgdependencies.h @@ -1,51 +1,51 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 KGDEPENDENCIES_H #define KGDEPENDENCIES_H // QtWidgets #include #include "konfiguratorpage.h" class QTabWidget; class KgDependencies : public KonfiguratorPage { Q_OBJECT public: explicit KgDependencies(bool first, QWidget* parent = nullptr); - int activeSubPage() Q_DECL_OVERRIDE; + int activeSubPage() override; private: void addApplication(const QString& name, QGridLayout *grid, int row, QWidget *parent, int page, const QString& additionalList = QString()); public slots: void slotApply(QObject *obj, const QString& configGroup, const QString& name); private: QTabWidget *tabWidget; }; #endif /* __KGDEPENDENCIES_H__ */ diff --git a/krusader/Konfigurator/kgpanel.h b/krusader/Konfigurator/kgpanel.h index 679f55ab..c7fcb159 100644 --- a/krusader/Konfigurator/kgpanel.h +++ b/krusader/Konfigurator/kgpanel.h @@ -1,61 +1,61 @@ /***************************************************************************** * Copyright (C) 2003 Csaba Karai * * Copyright (C) 2004-2019 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 KGPANEL_H #define KGPANEL_H #include "konfiguratorpage.h" class KrTreeWidget; class KrViewInstance; class KgPanel : public KonfiguratorPage { Q_OBJECT public: explicit KgPanel(bool first, QWidget* parent = nullptr); - int activeSubPage() Q_DECL_OVERRIDE; + int activeSubPage() override; protected: KonfiguratorCheckBoxGroup *panelToolbarButtonsCheckboxes; KonfiguratorCheckBoxGroup *buttonsCheckboxes; KonfiguratorRadioButtons *mouseRadio; KonfiguratorCheckBoxGroup *mouseCheckboxes; KrTreeWidget* mousePreview; protected slots: void slotEnablePanelToolbar(); void slotSelectionModeChanged(); void slotMouseCheckBoxChanged(); private: void setupGeneralTab(); void setupPanelTab(); void setupButtonsTab(); void setupMouseModeTab(); void setupMediaMenuTab(); void setupLayoutTab(); void setupView(KrViewInstance *instance, QWidget *parent); QTabWidget *tabWidget; }; #endif /* __KGPANEL_H__ */ diff --git a/krusader/Konfigurator/kgprotocols.h b/krusader/Konfigurator/kgprotocols.h index fad72f4b..12929714 100644 --- a/krusader/Konfigurator/kgprotocols.h +++ b/krusader/Konfigurator/kgprotocols.h @@ -1,73 +1,73 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 KGPROTOCOLS_H #define KGPROTOCOLS_H // QtWidgets #include #include "konfiguratorpage.h" #include "../GUI/krtreewidget.h" #include "../GUI/krlistwidget.h" class KgProtocols : public KonfiguratorPage { Q_OBJECT public: explicit KgProtocols(bool first, QWidget* parent = nullptr); - void loadInitialValues() Q_DECL_OVERRIDE; - void setDefaults() Q_DECL_OVERRIDE; - bool apply() Q_DECL_OVERRIDE; - bool isChanged() Q_DECL_OVERRIDE; + void loadInitialValues() override; + void setDefaults() override; + bool apply() override; + bool isChanged() override; static void init(); public slots: void slotDisableButtons(); void slotAddProtocol(); void slotRemoveProtocol(); void slotAddMime(); void slotRemoveMime(); protected: void loadProtocols(); void loadMimes(); void addSpacer(QBoxLayout *parent); void addProtocol(const QString& name, bool changeCurrent = false); void removeProtocol(const QString& name); void addMime(QString name, const QString& protocol); void removeMime(const QString& name); KrTreeWidget *linkList; KrListWidget *protocolList; KrListWidget *mimeList; QPushButton *btnAddProtocol; QPushButton *btnRemoveProtocol; QPushButton *btnAddMime; QPushButton *btnRemoveMime; }; #endif /* __KgProtocols_H__ */ diff --git a/krusader/Konfigurator/konfigurator.h b/krusader/Konfigurator/konfigurator.h index 10e4063f..3756db23 100644 --- a/krusader/Konfigurator/konfigurator.h +++ b/krusader/Konfigurator/konfigurator.h @@ -1,78 +1,78 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KONFIGURATOR_H #define KONFIGURATOR_H #include "konfiguratorpage.h" // QtCore #include #include class QString; class QResizeEvent; class QCloseEvent; class Konfigurator : public KPageDialog { Q_OBJECT signals: void configChanged(bool isGUIRestartNeeded); public: explicit Konfigurator(bool f = false, int startPage = 0); // true if Konfigurator is run for the first time - void reject() Q_DECL_OVERRIDE; + void reject() override; protected: void newPage(KonfiguratorPage *, const QString &, const QString &, const QIcon &); // adds widget and connects to slot void createLayout(int startPage); void closeDialog(); - void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *e) override; + void closeEvent(QCloseEvent *event) override; protected slots: void slotApplyEnable(); bool slotPageSwitch(KPageWidgetItem *, KPageWidgetItem *); void slotRestorePage(); void slotClose(); void slotApply(); void slotReset(); void slotRestoreDefaults(); void slotShowHelp(); private: QList kgPages; bool firstTime; KPageWidgetItem *lastPage; bool internalCall; QTimer restoreTimer; int sizeX; int sizeY; }; #endif diff --git a/krusader/Konfigurator/konfiguratoritems.h b/krusader/Konfigurator/konfiguratoritems.h index 93592848..c20bdaa2 100644 --- a/krusader/Konfigurator/konfiguratoritems.h +++ b/krusader/Konfigurator/konfiguratoritems.h @@ -1,427 +1,427 @@ /***************************************************************************** * Copyright (C) 2003 Csaba Karai * * Copyright (C) 2004-2019 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 KONFIGURATORITEMS_H #define KONFIGURATORITEMS_H // QtCore #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include "../GUI/krlistwidget.h" #define FIRST_PAGE 0 class KonfiguratorExtension : public QObject { Q_OBJECT public: KonfiguratorExtension(QObject *obj, QString cfgGroup, QString cfgName, bool restartNeeded = false, int page = FIRST_PAGE); virtual void loadInitialValue(); virtual bool apply(); virtual void setDefaults(); virtual bool isChanged(); virtual void setSubPage(int page) { subpage = page; } virtual int subPage() { return subpage; } inline QObject *object() { return objectPtr; } inline QString getConfigGroup() { return configGroup; } inline QString getConfigName() { return configName; } public slots: void setChanged() { emit sigChanged(changed = true); } void setChanged(bool chg) { emit sigChanged(changed = chg); } signals: void applyManually(QObject *, QString, QString); void applyAuto(QObject *, QString, QString); void setDefaultsManually(QObject *); void setDefaultsAuto(QObject *); void setInitialValue(QObject *); void sigChanged(bool); protected: QObject *objectPtr; bool applyConnected; bool setDefaultsConnected; bool changed; bool restartNeeded; int subpage; QString configGroup; QString configName; - void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; + void connectNotify(const QMetaMethod &signal) override; }; // KonfiguratorCheckBox class /////////////////////////////// class KonfiguratorCheckBox : public QCheckBox { Q_OBJECT public: KonfiguratorCheckBox(QString configGroup, QString name, bool defaultValue, const QString& text, QWidget *parent = nullptr, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorCheckBox() override; inline KonfiguratorExtension *extension() { return ext; } // indicate that a checkobox is dependent of this, // meaning that dep is only available if this box is checked void addDep(KonfiguratorCheckBox *dep); public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); protected: - void checkStateSet() Q_DECL_OVERRIDE; - void nextCheckState() Q_DECL_OVERRIDE; + void checkStateSet() override; + void nextCheckState() override; void updateDeps(); bool defaultValue; KonfiguratorExtension *ext; QList deps; }; // KonfiguratorSpinBox class /////////////////////////////// class KonfiguratorSpinBox : public QSpinBox { Q_OBJECT public: KonfiguratorSpinBox(QString configGroup, QString configName, int defaultValue, int min, int max, QWidget *parent = nullptr, bool restartNeeded = false, int page = FIRST_PAGE); ~KonfiguratorSpinBox() override; inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); protected: int defaultValue; KonfiguratorExtension *ext; }; // KonfiguratorCheckBoxGroup class /////////////////////////////// class KonfiguratorCheckBoxGroup : public QWidget { public: explicit KonfiguratorCheckBoxGroup(QWidget *parent = nullptr) : QWidget(parent){} void add(KonfiguratorCheckBox *); int count() { return checkBoxList.count(); }; KonfiguratorCheckBox * find(int index); KonfiguratorCheckBox * find(const QString& name); private: QList checkBoxList; }; // KonfiguratorRadioButtons class /////////////////////////////// class KonfiguratorRadioButtons : public QWidget { Q_OBJECT public: KonfiguratorRadioButtons(QString configGroup, QString name, QString defaultValue, QWidget *parent = nullptr, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorRadioButtons() override; inline KonfiguratorExtension *extension() { return ext; } void addRadioButton(QRadioButton *radioWidget, const QString& name, const QString& value); void selectButton(const QString& value); int count() { return radioButtons.count(); } QString selectedValue(); QRadioButton *find(int index); QRadioButton *find(const QString& name); public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); protected: QList radioButtons; QList radioValues; QList radioNames; QString defaultValue; KonfiguratorExtension *ext; }; // KonfiguratorEditBox class /////////////////////////////// class KonfiguratorEditBox : public QLineEdit { Q_OBJECT public: KonfiguratorEditBox(QString configGroup, QString name, QString defaultValue, QWidget *parent = nullptr, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorEditBox() override; inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); protected: QString defaultValue; KonfiguratorExtension *ext; }; // KonfiguratorURLRequester class /////////////////////////////// class KonfiguratorURLRequester : public KUrlRequester { Q_OBJECT public: KonfiguratorURLRequester(QString configGroup, QString name, QString defaultValue, QWidget *parent = nullptr, bool restart = false, int page = FIRST_PAGE, bool expansion = true); ~KonfiguratorURLRequester() override; inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); protected: QString defaultValue; KonfiguratorExtension *ext; bool expansion; }; // KonfiguratorFontChooser class /////////////////////////////// class KonfiguratorFontChooser : public QWidget { Q_OBJECT public: KonfiguratorFontChooser(QString configGroup, QString name, const QFont& defaultValue, QWidget *parent = nullptr, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorFontChooser() override; inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); void slotBrowseFont(); protected: QFont defaultValue; QFont font; KonfiguratorExtension *ext; QLabel * pLabel; QToolButton * pToolButton; void setFont(); }; // KONFIGURATOR_NAME_VALUE_PAIR structure /////////////////////////////// struct KONFIGURATOR_NAME_VALUE_PAIR { QString text; QString value; }; // KONFIGURATOR_NAME_VALUE_TIP structure /////////////////////////////// struct KONFIGURATOR_NAME_VALUE_TIP { QString text; QString value; QString tooltip; }; // KonfiguratorComboBox class /////////////////////////////// class KonfiguratorComboBox : public QComboBox { Q_OBJECT public: KonfiguratorComboBox(QString configGroup, QString name, QString defaultValue, KONFIGURATOR_NAME_VALUE_PAIR *listIn, int listInLen, QWidget *parent = nullptr, bool restart = false, bool editable = false, int page = FIRST_PAGE); ~KonfiguratorComboBox() override; inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); protected: QString defaultValue; KONFIGURATOR_NAME_VALUE_PAIR *list; int listLen; KonfiguratorExtension *ext; void selectEntry(const QString& entry); }; // KonfiguratorColorChooser class /////////////////////////////// typedef struct { QString name; QColor color; QString value; } ADDITIONAL_COLOR; class KonfiguratorColorChooser : public QComboBox { Q_OBJECT public: KonfiguratorColorChooser(QString configGroup, QString name, const QColor& defaultValue, QWidget *parent = nullptr, bool restart = false, ADDITIONAL_COLOR *addColPtr = nullptr, int addColNum = 0, int page = FIRST_PAGE); ~KonfiguratorColorChooser() override; inline KonfiguratorExtension *extension() { return ext; } void setDefaultColor(QColor dflt); void setDefaultText(const QString& text); QColor getColor(); void changeAdditionalColor(int num, const QColor& color); QString getValue(); bool isValueRGB(); void setValue(const QString& value); public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); void slotCurrentChanged(int number); signals: void colorChanged(); private: void addColor(const QString& text, const QColor& color); QPixmap createPixmap(const QColor& color); protected: QColor defaultValue; QColor customValue; QList palette; QList additionalColors; KonfiguratorExtension *ext; bool disableColorChooser; }; // KonfiguratorListBox class /////////////////////////////// class KonfiguratorListBox : public KrListWidget { Q_OBJECT public: KonfiguratorListBox(QString configGroup, QString name, QStringList defaultValue, QWidget *parent = nullptr, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorListBox() override; inline KonfiguratorExtension *extension() { return ext; } void addItem(const QString &); void removeItem(const QString &); public slots: virtual void loadInitialValue(); void slotApply(QObject *, const QString&, const QString&); void slotSetDefaults(QObject *); protected: QStringList list(); void setList(const QStringList&); QStringList defaultValue; KonfiguratorExtension *ext; }; #endif /* __KONFIGURATOR_ITEMS_H__ */ diff --git a/krusader/Konfigurator/krresulttable.h b/krusader/Konfigurator/krresulttable.h index d3c1c9b0..ac328c12 100644 --- a/krusader/Konfigurator/krresulttable.h +++ b/krusader/Konfigurator/krresulttable.h @@ -1,119 +1,119 @@ /***************************************************************************** * Copyright (C) 2005 Dirk Eschler * * Copyright (C) 2005-2019 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 KRRESULTTABLE_H #define KRRESULTTABLE_H // QtCore #include #include #include // QtWidgets #include #include #include #include #include #include #include "searchobject.h" class KrResultTable : public QWidget { public: explicit KrResultTable(QWidget* parent); ~KrResultTable() override; /** * Adds a row of search results to the end of a QGridLayout * Each KrResultTable has to implement it * * @param search Name of the SearchObject * @param grid The GridLayout where the row is inserted * * @return bool True if row was added successfully to rows, else false */ virtual bool addRow(SearchObject* search, QGridLayout* grid) = 0; protected: QStringList _supported; QStringList _tableHeaders; int _numColumns; int _numRows; QGridLayout* _grid; QLabel* _label; // generic label /** * Creates the main grid layout and attaches the table header * * @return bool Pointer to the main grid layout */ QGridLayout* initTable(); /** * Applies settings to each cell of the grid layout * Supposed to be run after a row was added * * @param grid The GridLayout */ void adjustRow(QGridLayout* grid); }; // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- class KrArchiverResultTable : public KrResultTable { Q_OBJECT public: explicit KrArchiverResultTable(QWidget* parent); ~KrArchiverResultTable() override; - bool addRow(SearchObject* search, QGridLayout* grid) Q_DECL_OVERRIDE; + bool addRow(SearchObject* search, QGridLayout* grid) override; protected: KUrlLabel* _nameLabel; protected slots: void website(const QString&); }; // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- class KrToolResultTable : public KrResultTable { Q_OBJECT public: explicit KrToolResultTable(QWidget* parent); ~KrToolResultTable() override; - bool addRow(SearchObject* search, QGridLayout* grid) Q_DECL_OVERRIDE; + bool addRow(SearchObject* search, QGridLayout* grid) override; protected: QList _apps; protected slots: void website(const QString&); }; #endif diff --git a/krusader/Locate/locate.cpp b/krusader/Locate/locate.cpp index e109212d..8be027a3 100644 --- a/krusader/Locate/locate.cpp +++ b/krusader/Locate/locate.cpp @@ -1,690 +1,690 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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" #include "../compat.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 { + void startDrag(Qt::DropActions supportedActs) 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; auto *drag = new QDrag(this); auto *mimeData = new QMimeData; mimeData->setImageData(FileListIcon("file").pixmap()); mimeData->setUrls(urls); drag->setMimeData(mimeData); drag->exec(); } }; KProcess * LocateDlg::updateProcess = nullptr; LocateDlg * LocateDlg::LocateDialog = nullptr; LocateDlg::LocateDlg(QWidget *parent) : QDialog(parent), isFeedToListBox(false) { setWindowTitle(i18n("Krusader::Locate")); setWindowModality(Qt::NonModal); auto *mainLayout = new QVBoxLayout; setLayout(mainLayout); auto *grid = new QGridLayout(); grid->setSpacing(6); grid->setContentsMargins(11, 11, 11, 11); QWidget *hboxWidget = new QWidget(this); auto *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); auto * hbox2 = new QHBoxLayout(hboxWidget2); hbox2->setContentsMargins(0, 0, 0, 0); auto* 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()).QFONTMETRICS_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, &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, &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, 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, QOverload::of(&KProcess::finished), this, &LocateDlg::updateFinished); updateProcess->start(); updateDbButton->setEnabled(false); } } void LocateDlg::updateFinished() { delete updateProcess; updateProcess = nullptr; 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(nullptr, i18n("Cannot start 'locate'. Check the 'Dependencies' page in konfigurator.")); return; } resultList->clear(); lastItem = nullptr; 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, &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 (auto & it : list) { 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(nullptr, 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(nullptr, 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 != nullptr) 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; auto *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) != nullptr); 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/Locate/locate.h b/krusader/Locate/locate.h index 30eb9494..9ff2b6ce 100644 --- a/krusader/Locate/locate.h +++ b/krusader/Locate/locate.h @@ -1,106 +1,106 @@ /***************************************************************************** * Copyright (C) 2004 Csaba Karai * * Copyright (C) 2004-2019 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 LOCATE_H #define LOCATE_H // QtGui #include // QtWidgets #include #include #include #include class KProcess; class KrTreeWidget; class QTreeWidgetItem; class LocateDlg : public QDialog { Q_OBJECT public: explicit LocateDlg(QWidget *parent); static LocateDlg *LocateDialog; virtual void feedToListBox(); void reset(); public slots: void slotFeedStop(); void slotUpdateDb(); void slotLocate(); void processStdout(); void processStderr(); void locateFinished(); void locateError(); void slotRightClick(QTreeWidgetItem *, const QPoint &); void slotDoubleClick(QTreeWidgetItem *); void updateFinished(); protected: - void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *) override; private: void operate(QTreeWidgetItem *item, int task); bool find(); void nextLine(); void updateButtons(bool locateIsRunning); bool dontSearchPath; bool onlyExist; bool isCs; bool isFeedToListBox; QString pattern; KHistoryComboBox *locateSearchFor; KrTreeWidget *resultList; QString remaining; QTreeWidgetItem *lastItem; QString collectedErr; long findOptions; QString findPattern; QTreeWidgetItem *findCurrentItem; QCheckBox *dontSearchInPath; QCheckBox *existingFiles; QCheckBox *caseSensitive; QPushButton *feedStopButton; QPushButton *updateDbButton; QPushButton *locateButton; KProcess *locateProc; static KProcess *updateProcess; }; #endif /* __LOCATE_H__ */ diff --git a/krusader/MountMan/kmountmangui.h b/krusader/MountMan/kmountmangui.h index cd62eac7..eacfd43b 100644 --- a/krusader/MountMan/kmountmangui.h +++ b/krusader/MountMan/kmountmangui.h @@ -1,194 +1,194 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KMOUNTMANGUI_H #define KMOUNTMANGUI_H // QtCore #include #include #include // QtWidgets #include #include #include #include #include "../GUI/krtreewidget.h" #include "kmountman.h" #define WATCHER_DELAY 500 class QCheckBox; class KRFSDisplay; // forward definitions class fsData; class KMountManGUI : public QDialog { Q_OBJECT enum Pages { Filesystems = 0 }; public: explicit KMountManGUI(KMountMan *mntMan); ~KMountManGUI() override; protected: - void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *e) override; protected slots: void doubleClicked(QTreeWidgetItem *); void clicked(QTreeWidgetItem *, const QPoint &); void slotToggleMount(); void slotEject(); void changeActive(); void changeActive(QTreeWidgetItem *); void checkMountChange(); // check whether the mount table was changed void updateList(); // fill-up the filesystems list void getSpaceData(); protected: QLayout *createMainPage(); // creator of the main page - filesystems void addItemToMountList(KrTreeWidget *lst, fsData &fs); fsData* getFsData(QTreeWidgetItem *item); QString getMntPoint(QTreeWidgetItem *item); void addNonMounted(); private: KMountMan *mountMan; KRFSDisplay *info; KrTreeWidget *mountList; QCheckBox *cbShowOnlyRemovable; QPushButton *mountButton; QPushButton *ejectButton; QTimer *watcher; QDateTime lastMtab; // used for the getSpace - gotSpace functions KMountPoint::List possible, mounted; QList fileSystems; int sizeX; int sizeY; }; // Data container for a single-filesystem data // maximum size supported is 2GB of 1kb blocks == 2048GB, enough. // not really needed, but kept for backward compatibility class fsData { public: fsData() : Name(), Type(), MntPoint(), TotalBlks(0), FreeBlks(0), Mounted(false) {} // get information inline QString name() { return Name; } inline QString shortName() { return Name.right(Name.length() - Name.indexOf("/", 1) - 1); } inline QString type() { return Type; } inline QString mntPoint() { return MntPoint; } inline long totalBlks() { return TotalBlks; } inline long freeBlks() { return FreeBlks; } inline KIO::filesize_t totalBytes() { return TotalBlks * 1024; } inline KIO::filesize_t freeBytes() { return FreeBlks * 1024; } //////////////////// insert a good round function here ///////////////// int usedPerct() { if (TotalBlks == 0) return 0; float res = ((float)(TotalBlks - FreeBlks)) / ((float) TotalBlks) * 100; if ((res - (int) res) > 0.5) return (int) res + 1; else return (int) res; } inline bool mounted() { return Mounted; } // set information inline void setName(QString n_) { Name = std::move(n_); } inline void setType(QString t_) { Type = std::move(t_); } inline void setMntPoint(QString m_) { MntPoint = std::move(m_); } inline void setTotalBlks(long t_) { TotalBlks = t_; } inline void setFreeBlks(long f_) { FreeBlks = f_; } inline void setMounted(bool m_) { Mounted = m_; } private: QString Name; // i.e: /dev/cdrom QString Type; // i.e: iso9600 QString MntPoint; // i.e: /mnt/cdrom long TotalBlks; // measured in 1024bytes per block long FreeBlks; bool Mounted; // true if filesystem is mounted // additional attributes of a filesystem, parsed from fstab public: QString options; // additional fstab options }; class KrMountDetector { QString checksum; #ifndef BSD QDateTime lastMtab; #endif public: KrMountDetector(); static KrMountDetector * getInstance(); bool hasMountsChanged(); }; #endif diff --git a/krusader/Panel/PanelView/krinterbriefview.h b/krusader/Panel/PanelView/krinterbriefview.h index 5c761ccf..c199cf2d 100644 --- a/krusader/Panel/PanelView/krinterbriefview.h +++ b/krusader/Panel/PanelView/krinterbriefview.h @@ -1,121 +1,121 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * Copyright (C) 2009-2019 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 KRINTERBRIEFVIEW_H #define KRINTERBRIEFVIEW_H // QtCore #include // QtGui #include // QtWidgets #include #include #include #include "krinterview.h" /** * @brief Compact view showing only icon and file name of view items */ class KrInterBriefView : public QAbstractItemView, public KrInterView { Q_OBJECT public: KrInterBriefView(QWidget *parent, KrViewInstance &instance, KConfig *cfg); ~KrInterBriefView() override; // ---- reimplemented from QAbstractItemView ---- - QRect visualRect(const QModelIndex&) const Q_DECL_OVERRIDE; - QModelIndex indexAt(const QPoint&) const Q_DECL_OVERRIDE; - void scrollTo(const QModelIndex &, QAbstractItemView::ScrollHint = QAbstractItemView::EnsureVisible) Q_DECL_OVERRIDE; + QRect visualRect(const QModelIndex&) const override; + QModelIndex indexAt(const QPoint&) const override; + void scrollTo(const QModelIndex &, QAbstractItemView::ScrollHint = QAbstractItemView::EnsureVisible) override; // ---- reimplemented from KrView ---- - int itemsPerPage() Q_DECL_OVERRIDE; - void updateView() Q_DECL_OVERRIDE; - bool ensureVisibilityAfterSelect() Q_DECL_OVERRIDE { + int itemsPerPage() override; + void updateView() override; + bool ensureVisibilityAfterSelect() override { return false; } - void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) Q_DECL_OVERRIDE; + void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) override; // ---- reimplemented from QAbstractItemView ---- // Don't do anything, selections are handled by the mouse handler - void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) Q_DECL_OVERRIDE {} - void selectAll() Q_DECL_OVERRIDE {} + void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) override {} + void selectAll() override {} // this shouldn't be called - QRegion visualRegionForSelection(const QItemSelection&) const Q_DECL_OVERRIDE { + QRegion visualRegionForSelection(const QItemSelection&) const override { return QRegion(); } // ---- reimplemented from KrView ---- - void setFileIconSize(int size) Q_DECL_OVERRIDE; + void setFileIconSize(int size) override; protected slots: // ---- reimplemented from QAbstractItemView ---- - void updateGeometries() Q_DECL_OVERRIDE; + void updateGeometries() override; // ---- reimplemented from KrView ---- - void currentChanged(const QModelIndex & current, const QModelIndex & previous) Q_DECL_OVERRIDE; + void currentChanged(const QModelIndex & current, const QModelIndex & previous) override; - void renameCurrentItem() Q_DECL_OVERRIDE; + void renameCurrentItem() override; protected: // ---- reimplemented from KrView ---- - bool handleKeyEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + bool handleKeyEvent(QKeyEvent *e) override; // ---- reimplemented from QAbstractItemView ---- - bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; - void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE; - QModelIndex moveCursor(QAbstractItemView::CursorAction, Qt::KeyboardModifiers) Q_DECL_OVERRIDE; - int horizontalOffset() const Q_DECL_OVERRIDE; - int verticalOffset() const Q_DECL_OVERRIDE; - bool isIndexHidden(const QModelIndex&) const Q_DECL_OVERRIDE; -// QRegion visualRegionForSelection(const QItemSelection&) const Q_DECL_OVERRIDE; - bool event(QEvent * e) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void mouseDoubleClickEvent(QMouseEvent *ev) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void wheelEvent(QWheelEvent *) Q_DECL_OVERRIDE; - void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; - void dragMoveEvent(QDragMoveEvent *e) Q_DECL_OVERRIDE; - void dragLeaveEvent(QDragLeaveEvent *e) Q_DECL_OVERRIDE; - void dropEvent(QDropEvent *) Q_DECL_OVERRIDE; + bool eventFilter(QObject *object, QEvent *event) override; + void keyPressEvent(QKeyEvent *e) override; + void paintEvent(QPaintEvent *e) override; + QModelIndex moveCursor(QAbstractItemView::CursorAction, Qt::KeyboardModifiers) override; + int horizontalOffset() const override; + int verticalOffset() const override; + bool isIndexHidden(const QModelIndex&) const override; +// QRegion visualRegionForSelection(const QItemSelection&) const override; + bool event(QEvent * e) override; + void mousePressEvent(QMouseEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void mouseDoubleClickEvent(QMouseEvent *ev) override; + void mouseMoveEvent(QMouseEvent *) override; + void wheelEvent(QWheelEvent *) override; + void dragEnterEvent(QDragEnterEvent *e) override; + void dragMoveEvent(QDragMoveEvent *e) override; + void dragLeaveEvent(QDragLeaveEvent *e) override; + void dropEvent(QDropEvent *) override; // ---- reimplemented from KrView ---- - void setup() Q_DECL_OVERRIDE; - void doRestoreSettings(KConfigGroup group) Q_DECL_OVERRIDE; - void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) Q_DECL_OVERRIDE; - void copySettingsFrom(KrView *other) Q_DECL_OVERRIDE; - QRect itemRect(const FileItem *fileitem) Q_DECL_OVERRIDE; - void showContextMenu(const QPoint & p) Q_DECL_OVERRIDE; + void setup() override; + void doRestoreSettings(KConfigGroup group) override; + void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) override; + void copySettingsFrom(KrView *other) override; + QRect itemRect(const FileItem *fileitem) override; + void showContextMenu(const QPoint & p) override; QRect mapToViewport(const QRect &rect) const; int getItemHeight() const; int elementWidth(const QModelIndex & index); void intersectionSet(const QRect &, QVector &); private: QFont _viewFont; int _numOfColumns; QHeaderView * _header; }; #endif // KRINTERBRIEFVIEW_H diff --git a/krusader/Panel/PanelView/krinterdetailedview.h b/krusader/Panel/PanelView/krinterdetailedview.h index 5d3191c4..4199e46b 100644 --- a/krusader/Panel/PanelView/krinterdetailedview.h +++ b/krusader/Panel/PanelView/krinterdetailedview.h @@ -1,96 +1,96 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 KRINTERDETAILEDVIEW_H #define KRINTERDETAILEDVIEW_H // QtCore #include // QtGui #include // QtWidgets #include #include "krinterview.h" class QMouseEvent; class QKeyEvent; class QDragEnterEvent; class KrInterDetailedView : public QTreeView, public KrInterView { Q_OBJECT public: KrInterDetailedView(QWidget *parent, KrViewInstance &instance, KConfig *cfg); ~KrInterDetailedView() override; - void updateView() Q_DECL_OVERRIDE; + void updateView() override; - bool ensureVisibilityAfterSelect() Q_DECL_OVERRIDE { + bool ensureVisibilityAfterSelect() override { return false; } - int itemsPerPage() Q_DECL_OVERRIDE; - void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) Q_DECL_OVERRIDE; - void setFileIconSize(int size) Q_DECL_OVERRIDE; - void doRestoreSettings(KConfigGroup grp) Q_DECL_OVERRIDE; + int itemsPerPage() override; + void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) override; + void setFileIconSize(int size) override; + void doRestoreSettings(KConfigGroup grp) override; protected slots: - void renameCurrentItem() Q_DECL_OVERRIDE; + void renameCurrentItem() override; void sectionResized(int, int, int); void sectionMoved(int, int, int); - void currentChanged(const QModelIndex & current, const QModelIndex & previous) Q_DECL_OVERRIDE; + void currentChanged(const QModelIndex & current, const QModelIndex & previous) override; protected: - void setup() Q_DECL_OVERRIDE; - void copySettingsFrom(KrView *other) Q_DECL_OVERRIDE; - void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) Q_DECL_OVERRIDE; + void setup() override; + void copySettingsFrom(KrView *other) override; + void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties) override; // Don't do anything, selections are handled by the mouse handler - void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) Q_DECL_OVERRIDE {} - void selectAll() Q_DECL_OVERRIDE {} + void setSelection(const QRect &, QItemSelectionModel::SelectionFlags) override {} + void selectAll() override {} - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void mouseDoubleClickEvent(QMouseEvent *ev) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE; - void wheelEvent(QWheelEvent *) Q_DECL_OVERRIDE; - bool event(QEvent * e) Q_DECL_OVERRIDE; - void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; - void dragMoveEvent(QDragMoveEvent *e) Q_DECL_OVERRIDE; - void dragLeaveEvent(QDragLeaveEvent *e) Q_DECL_OVERRIDE; - void dropEvent(QDropEvent *) Q_DECL_OVERRIDE; - bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE; - bool viewportEvent(QEvent * event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) override; + void mousePressEvent(QMouseEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void mouseDoubleClickEvent(QMouseEvent *ev) override; + void mouseMoveEvent(QMouseEvent *) override; + void wheelEvent(QWheelEvent *) override; + bool event(QEvent * e) override; + void dragEnterEvent(QDragEnterEvent *e) override; + void dragMoveEvent(QDragMoveEvent *e) override; + void dragLeaveEvent(QDragLeaveEvent *e) override; + void dropEvent(QDropEvent *) override; + bool eventFilter(QObject *object, QEvent *event) override; + bool viewportEvent(QEvent * event) override; void drawRow(QPainter *painter, const QStyleOptionViewItem &options, - const QModelIndex &index) const Q_DECL_OVERRIDE; + const QModelIndex &index) const override; - QRect itemRect(const FileItem *fileitem) Q_DECL_OVERRIDE; + QRect itemRect(const FileItem *fileitem) override; - void showContextMenu(const QPoint & p) Q_DECL_OVERRIDE; + void showContextMenu(const QPoint & p) override; void recalculateColumnSizes(); private: QFont _viewFont; bool _autoResizeColumns; }; #endif // __krinterview__ diff --git a/krusader/Panel/PanelView/krinterview.h b/krusader/Panel/PanelView/krinterview.h index 22e4db0e..596fed9b 100644 --- a/krusader/Panel/PanelView/krinterview.h +++ b/krusader/Panel/PanelView/krinterview.h @@ -1,124 +1,124 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2010 Jan Lepper * * Copyright (C) 2004-2019 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 KRINTERVIEW_H #define KRINTERVIEW_H // QtCore #include // QtWidgets #include #include "krview.h" class ListModel; class KrMouseHandler; class KrViewItem; /** * @brief Abstract intermediate class between KrView and full view implementations. * * It contains the methods common to all implementing subclasses of KrView. */ class KrInterView : public KrView { friend class KrViewItem; public: KrInterView(KrViewInstance &instance, KConfig *cfg, QAbstractItemView *itemView); virtual ~KrInterView(); - QModelIndex getCurrentIndex() Q_DECL_OVERRIDE { + QModelIndex getCurrentIndex() override { return _itemView->currentIndex(); } - bool isSelected(const QModelIndex &ndx) Q_DECL_OVERRIDE; - uint numSelected() const Q_DECL_OVERRIDE { + bool isSelected(const QModelIndex &ndx) override; + uint numSelected() const override { return _selection.count(); } - QList selectedUrls() Q_DECL_OVERRIDE; - void setSelectionUrls(const QList urls) Q_DECL_OVERRIDE; - KrViewItem* getFirst() Q_DECL_OVERRIDE; - KrViewItem* getLast() Q_DECL_OVERRIDE; - KrViewItem* getNext(KrViewItem *current) Q_DECL_OVERRIDE; - KrViewItem* getPrev(KrViewItem *current) Q_DECL_OVERRIDE; - KrViewItem* getCurrentKrViewItem() Q_DECL_OVERRIDE; - KrViewItem* findItemByName(const QString &name) Q_DECL_OVERRIDE; - KrViewItem *findItemByUrl(const QUrl &url) Q_DECL_OVERRIDE; - QString getCurrentItem() const Q_DECL_OVERRIDE; - KrViewItem *getKrViewItemAt(const QPoint &vp) Q_DECL_OVERRIDE; + QList selectedUrls() override; + void setSelectionUrls(const QList urls) override; + KrViewItem* getFirst() override; + KrViewItem* getLast() override; + KrViewItem* getNext(KrViewItem *current) override; + KrViewItem* getPrev(KrViewItem *current) override; + KrViewItem* getCurrentKrViewItem() override; + KrViewItem* findItemByName(const QString &name) override; + KrViewItem *findItemByUrl(const QUrl &url) override; + QString getCurrentItem() const override; + KrViewItem *getKrViewItemAt(const QPoint &vp) override; void setCurrentItem(const QString &name, bool scrollToCurrent = true, - const QModelIndex &fallbackToIndex = QModelIndex()) Q_DECL_OVERRIDE; - void setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent = true) Q_DECL_OVERRIDE; - void makeItemVisible(const KrViewItem *item) Q_DECL_OVERRIDE; - bool isItemVisible(const KrViewItem *item) Q_DECL_OVERRIDE; - void clear() Q_DECL_OVERRIDE; - void sort() Q_DECL_OVERRIDE; - void refreshColors() Q_DECL_OVERRIDE; - void redraw() Q_DECL_OVERRIDE; - void prepareForActive() Q_DECL_OVERRIDE; - void prepareForPassive() Q_DECL_OVERRIDE; - void selectRegion(KrViewItem *i1, KrViewItem *i2, bool select) Q_DECL_OVERRIDE; + const QModelIndex &fallbackToIndex = QModelIndex()) override; + void setCurrentKrViewItem(KrViewItem *item, bool scrollToCurrent = true) override; + void makeItemVisible(const KrViewItem *item) override; + bool isItemVisible(const KrViewItem *item) override; + void clear() override; + void sort() override; + void refreshColors() override; + void redraw() override; + void prepareForActive() override; + void prepareForPassive() override; + void selectRegion(KrViewItem *i1, KrViewItem *i2, bool select) override; void sortModeUpdated(int column, Qt::SortOrder order); void redrawItem(FileItem *fileitem) { _itemView->viewport()->update(itemRect(fileitem)); } protected: class DummySelectionModel : public QItemSelectionModel { public: DummySelectionModel(QAbstractItemModel *model, QObject *parent) : QItemSelectionModel(model, parent) {} // do nothing - selection is managed by KrInterView - void select(const QModelIndex &, QItemSelectionModel::SelectionFlags) Q_DECL_OVERRIDE {} - void select(const QItemSelection &, QItemSelectionModel::SelectionFlags) Q_DECL_OVERRIDE {} + void select(const QModelIndex &, QItemSelectionModel::SelectionFlags) override {} + void select(const QItemSelection &, QItemSelectionModel::SelectionFlags) override {} }; - KIO::filesize_t calcSize() Q_DECL_OVERRIDE; - KIO::filesize_t calcSelectedSize() Q_DECL_OVERRIDE; - void populate(const QList &fileItems, FileItem *dummy) Q_DECL_OVERRIDE; - KrViewItem* preAddItem(FileItem *fileitem) Q_DECL_OVERRIDE; + KIO::filesize_t calcSize() override; + KIO::filesize_t calcSelectedSize() override; + void populate(const QList &fileItems, FileItem *dummy) override; + KrViewItem* preAddItem(FileItem *fileitem) override; /** * Remove an item. Does not handle new current selection. */ - void preDeleteItem(KrViewItem *item) Q_DECL_OVERRIDE; - void intSetSelected(const FileItem* fileitem, bool select) Q_DECL_OVERRIDE; + void preDeleteItem(KrViewItem *item) override; + void intSetSelected(const FileItem* fileitem, bool select) override; virtual QRect itemRect(const FileItem *fileitem) = 0; KrViewItem * getKrViewItem(FileItem *fileitem); KrViewItem * getKrViewItem(const QModelIndex &); bool isSelected(const FileItem *fileitem) const { return _selection.contains(fileitem); } void makeCurrentVisible(); ListModel *_model; QAbstractItemView *_itemView; KrMouseHandler *_mouseHandler; QHash _itemHash; QSet _selection; private: void setCurrent(const QModelIndex &index, bool scrollToCurrent); }; #endif diff --git a/krusader/Panel/PanelView/krselectionmode.h b/krusader/Panel/PanelView/krselectionmode.h index c545db9e..6a366798 100644 --- a/krusader/Panel/PanelView/krselectionmode.h +++ b/krusader/Panel/PanelView/krselectionmode.h @@ -1,167 +1,167 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 KRSELECTIONMODE_H #define KRSELECTIONMODE_H // QtCore #include /** Every selection mode inherits this class, and has to implement init(). Usage: KrSelectionMode::getSelectionHandler()->whateverFunctionYouNeed() \note You can call KrSelectionMode::resetSelectionHandler() if you want the selection mode to be re-read. This is useful after a configuration where you changed the selection mode. calling resetSelectionHandler() will cause the next call to getSelectionHandler() to (possibly) select a different mode. */ class KrSelectionMode { public: static KrSelectionMode * getSelectionHandlerForMode(const QString &mode); static KrSelectionMode * getSelectionHandler(); static void resetSelectionHandler(); virtual void init() = 0; // everyone must implement this in order to be a selection mode inline bool useQTSelection() { return _useQTSelection; } inline bool spaceMovesDown() { return _spaceMovesDown; } inline bool insertMovesDown() { return _insertMovesDown; } inline bool spaceCalculatesDiskSpace() { return _spaceCalculatesDiskSpace; } inline bool rightButtonSelects() { return _rightButtonSelects; } inline bool leftButtonSelects() { return _leftButtonSelects; } inline bool rightButtonPreservesSelection() { return _rightButtonPreservesSelection; } inline bool leftButtonPreservesSelection() { return _leftButtonPreservesSelection; } inline bool shiftCtrlRightButtonSelects() { return _shiftCtrlRightButtonSelects; } inline bool shiftCtrlLeftButtonSelects() { return _shiftCtrlLeftButtonSelects; } inline int showContextMenu() { return _showContextMenu; } // 0: no, -1: yes, n>0: after n milliseconds virtual ~KrSelectionMode() {} protected: bool _useQTSelection, _spaceMovesDown, _insertMovesDown, _spaceCalculatesDiskSpace; bool _rightButtonSelects, _leftButtonSelects, _rightButtonPreservesSelection; bool _leftButtonPreservesSelection, _shiftCtrlRightButtonSelects, _shiftCtrlLeftButtonSelects; int _showContextMenu; }; class KonqSelectionMode : public KrSelectionMode { public: - void init() Q_DECL_OVERRIDE { + void init() override { _useQTSelection = true; _spaceMovesDown = false; _insertMovesDown = true; _spaceCalculatesDiskSpace = false; _rightButtonSelects = true; _leftButtonSelects = true; _rightButtonPreservesSelection = false; _leftButtonPreservesSelection = false; _shiftCtrlRightButtonSelects = false; _shiftCtrlLeftButtonSelects = false; _showContextMenu = -1; } }; class OriginalSelectionMode : public KrSelectionMode { public: - void init() Q_DECL_OVERRIDE { + void init() override { _useQTSelection = false; _spaceMovesDown = true; _insertMovesDown = true; _spaceCalculatesDiskSpace = true; _rightButtonSelects = true; _leftButtonSelects = true; _rightButtonPreservesSelection = false; _leftButtonPreservesSelection = false; _shiftCtrlRightButtonSelects = false; _shiftCtrlLeftButtonSelects = false; _showContextMenu = -1; } }; class TCSelectionMode : public KrSelectionMode { public: - void init() Q_DECL_OVERRIDE { + void init() override { _useQTSelection = false; _spaceMovesDown = false; _insertMovesDown = true; _spaceCalculatesDiskSpace = true; _rightButtonSelects = true; _leftButtonSelects = false; _rightButtonPreservesSelection = true; _leftButtonPreservesSelection = false; _shiftCtrlRightButtonSelects = false; _shiftCtrlLeftButtonSelects = true; _showContextMenu = 500; } }; class ErgonomicSelectionMode : public KrSelectionMode { public: - void init() Q_DECL_OVERRIDE { + void init() override { _useQTSelection = false; _spaceMovesDown = false; _insertMovesDown = true; _spaceCalculatesDiskSpace = true; _rightButtonSelects = false; _leftButtonSelects = false; _rightButtonPreservesSelection = true; _leftButtonPreservesSelection = true; _shiftCtrlRightButtonSelects = false; _shiftCtrlLeftButtonSelects = true; _showContextMenu = -1; } }; class UserSelectionMode: public KrSelectionMode { public: - void init() Q_DECL_OVERRIDE; + void init() override; }; #endif // KR_SELECTION_MODE_H diff --git a/krusader/Panel/PanelView/krviewfactory.cpp b/krusader/Panel/PanelView/krviewfactory.cpp index 24768b2b..7e95cb20 100644 --- a/krusader/Panel/PanelView/krviewfactory.cpp +++ b/krusader/Panel/PanelView/krviewfactory.cpp @@ -1,107 +1,107 @@ /***************************************************************************** * Copyright (C) 2000-2007 Shie Erlich * * Copyright (C) 2000-2007 Rafi Yanai * * Copyright (C) 2000-2007 Csaba Karai * * Copyright (C) 2004-2019 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 "krviewfactory.h" #include "krinterdetailedview.h" #include "krinterbriefview.h" #include #include KrViewInstance::KrViewInstance(int id, const QString &name, const QString &desc, const QString &iconName, const QKeySequence &shortcut) : m_id(id), m_name(name), m_description(desc), m_iconName(iconName), m_shortcut(shortcut) { } template class KrViewInstanceImpl : public KrViewInstance { public: KrViewInstanceImpl(int id, const QString &name, const QString &desc, const QString &icon, const QKeySequence &shortcut) : KrViewInstance(id, name, desc, icon, shortcut) {} - KrView *create(QWidget *w, KConfig *cfg) Q_DECL_OVERRIDE { + KrView *create(QWidget *w, KConfig *cfg) override { return new T(w, *this, cfg); } }; KrViewFactory::KrViewFactory() : m_defaultViewId(-1) {} // static initialization, on first use idiom KrViewFactory &KrViewFactory::self() { static KrViewFactory *factory = nullptr; if (!factory) { factory = new KrViewFactory(); factory->init(); } return *factory; } void KrViewFactory::init() { registerView(new KrViewInstanceImpl (0, "KrInterDetailedView", i18n("&Detailed View"), "view-list-details", Qt::ALT + Qt::SHIFT + Qt::Key_D)); registerView(new KrViewInstanceImpl (1, "KrInterBriefView", i18n("&Brief View"), "view-list-icons", Qt::ALT + Qt::SHIFT + Qt::Key_B)); } KrView *KrViewFactory::createView(int id, QWidget *widget, KConfig *cfg) { return self().viewInstance(id)->create(widget, cfg); } void KrViewFactory::registerView(KrViewInstance *inst) { int position = 0; while (position < m_registeredViews.count()) { if (m_registeredViews[position]->id() > inst->id()) break; position++; } m_registeredViews.insert(m_registeredViews.begin() + position, inst); if (m_defaultViewId == -1 || inst->id() < m_defaultViewId) m_defaultViewId = inst->id(); } KrViewInstance *KrViewFactory::viewInstance(int id) { foreach (KrViewInstance *inst, m_registeredViews) { if (inst->id() == id) return inst; } foreach (KrViewInstance *inst_dflt, m_registeredViews) { if (inst_dflt->id() == m_defaultViewId) return inst_dflt; } fprintf(stderr, "Internal Error: no views registered!\n"); exit(-1); } diff --git a/krusader/Panel/PanelView/krviewitemdelegate.h b/krusader/Panel/PanelView/krviewitemdelegate.h index 7e139054..e7b0fdce 100644 --- a/krusader/Panel/PanelView/krviewitemdelegate.h +++ b/krusader/Panel/PanelView/krviewitemdelegate.h @@ -1,48 +1,48 @@ /***************************************************************************** * Copyright (C) 2009 Csaba Karai * * Copyright (C) 2009-2019 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 KRVIEWITEMDELEGATE_H #define KRVIEWITEMDELEGATE_H // QtWidgets #include class KrViewItemDelegate : public QItemDelegate { public: explicit KrViewItemDelegate(QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const Q_DECL_OVERRIDE; + const QModelIndex &index) const override; void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, - const QString &text) const Q_DECL_OVERRIDE; + const QString &text) const override; QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &sovi, - const QModelIndex &index) const Q_DECL_OVERRIDE; - void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE; + const QModelIndex &index) const override; + void setEditorData(QWidget *editor, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, - const QModelIndex &index) const Q_DECL_OVERRIDE; - bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE; + const QModelIndex &index) const override; + bool eventFilter(QObject *object, QEvent *event) override; private: mutable int _currentlyEdited; mutable bool _dontDraw; }; #endif diff --git a/krusader/Panel/PanelView/listmodel.h b/krusader/Panel/PanelView/listmodel.h index fb286a21..826ee4e6 100644 --- a/krusader/Panel/PanelView/listmodel.h +++ b/krusader/Panel/PanelView/listmodel.h @@ -1,121 +1,121 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 LISTMODEL_H #define LISTMODEL_H // QtCore #include // QtGui #include #include "krsort.h" class FileItem; class KrInterView; class KrViewProperties; /** * @brief The list model for all panel views. */ class ListModel: public QAbstractListModel { Q_OBJECT public: explicit ListModel(KrInterView *); ~ListModel() override; inline bool ready() const { return _ready; } void populate(const QList &files, FileItem *dummy); QModelIndex addItem(FileItem *); void removeItem(FileItem *); - int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; - bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; void setExtensionEnabled(bool exten) { _extensionEnabled = exten; } const KrViewProperties * properties() const; void sort() { sort(lastSortOrder(), lastSortDir()); } void clear(bool emitLayoutChanged = true); QList fileItems() { return _fileItems; } FileItem * fileItemAt(const QModelIndex &index); FileItem *dummyFileItem() const { return _dummyFileItem; } const QModelIndex & fileItemIndex(const FileItem *); const QModelIndex & nameIndex(const QString &); const QModelIndex & indexFromUrl(const QUrl &url); - Qt::ItemFlags flags(const QModelIndex & index) const Q_DECL_OVERRIDE; + Qt::ItemFlags flags(const QModelIndex & index) const override; void emitChanged() { emit layoutChanged(); } Qt::SortOrder lastSortDir() const; int lastSortOrder() const; void setAlternatingTable(bool altTable) { _alternatingTable = altTable; } public slots: - void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) Q_DECL_OVERRIDE; + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; protected: KrSort::LessThanFunc lessThanFunc() { return KrSort::itemLessThan; } KrSort::LessThanFunc greaterThanFunc() const { return KrSort::itemGreaterThan; } QVariant customSortData(FileItem *) const { return QVariant(); } KrSort::Sorter createSorter(); QString nameWithoutExtension(const FileItem * fileitem, bool checkEnabled = true) const; private: void updateIndices(FileItem *file, int index); QString toolTipText(FileItem *fileItem) const; static QString dateText(time_t time); QList _fileItems; QHash _fileItemNdx; QHash _nameNdx; QHash _urlNdx; bool _extensionEnabled; KrInterView * _view; FileItem * _dummyFileItem; bool _ready; QFont _defaultFont; bool _justForSizeHint; bool _alternatingTable; }; #endif // __listmodel__ diff --git a/krusader/Panel/krcalcspacedialog.h b/krusader/Panel/krcalcspacedialog.h index 2a69f45d..cf2403e2 100644 --- a/krusader/Panel/krcalcspacedialog.h +++ b/krusader/Panel/krcalcspacedialog.h @@ -1,60 +1,60 @@ /***************************************************************************** * Copyright (C) 2004 Shie Erlich * * Copyright (C) 2004 Rafi Yanai * * Copyright (C) 2004-2019 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 KRCALCSPACEDIALOG_H #define KRCALCSPACEDIALOG_H // QtWidgets #include #include #include class SizeCalculator; /** Dialog showing the number of files and directories and its total size for a calculation. */ class KrCalcSpaceDialog : public QDialog { Q_OBJECT public: /** * Create and show a dialog. If delayed is true the dialog is shown with a delay of 2 seconds * to avoid a short appearance and is autoclosed when the calculation finished. */ static void showDialog(QWidget *parent, SizeCalculator *calculator); - void closeEvent(QCloseEvent *) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void closeEvent(QCloseEvent *) override; + void keyPressEvent(QKeyEvent *e) override; private slots: void slotCancel(); // cancel was pressed void slotCalculatorFinished(); void updateResult(); // show the current result in the dialog private: KrCalcSpaceDialog(QWidget *parent, SizeCalculator *calculator); SizeCalculator *const m_calculator; QLabel *m_label; QDialogButtonBox *m_buttonBox; QTimer *m_updateTimer; }; #endif diff --git a/krusader/Panel/krfiletreeview.cpp b/krusader/Panel/krfiletreeview.cpp index 8791066b..5b7deb9a 100644 --- a/krusader/Panel/krfiletreeview.cpp +++ b/krusader/Panel/krfiletreeview.cpp @@ -1,401 +1,401 @@ /***************************************************************************** * Copyright (C) 2010 Jan Lepper * * Copyright (C) 2010-2019 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 "krfiletreeview.h" #include "panelfunc.h" #include "../defaults.h" #include "../krglobal.h" #include "../icon.h" #include "../FileSystem/filesystemprovider.h" #include "../compat.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class KrDirModel : public KDirModel { public: KrDirModel(QWidget *parent, KrFileTreeView *ftv) : KDirModel(parent), fileTreeView(ftv) {} protected: - Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE + Qt::ItemFlags flags(const QModelIndex &index) const override { Qt::ItemFlags itflags = KDirModel::flags(index); if (index.column() != KDirModel::Name) itflags &= ~Qt::ItemIsDropEnabled; return itflags; } private: KrFileTreeView *fileTreeView; }; class TreeStyle : public QProxyStyle { public: explicit TreeStyle(QStyle *style) : QProxyStyle(style) {} int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, - QStyleHintReturn *returnData) const Q_DECL_OVERRIDE + QStyleHintReturn *returnData) const override { if (hint == QStyle::SH_ItemView_ActivateItemOnSingleClick) { return true; } return QProxyStyle::styleHint(hint, option, widget, returnData); } }; KrFileTreeView::KrFileTreeView(QWidget *parent) : QTreeView(parent), mStartTreeFromCurrent(false), mStartTreeFromPlace(true) { mSourceModel = new KrDirModel(this, this); mSourceModel->dirLister()->setDirOnlyMode(true); mProxyModel = new KDirSortFilterProxyModel(this); mProxyModel->setSourceModel(mSourceModel); setModel(mProxyModel); mFilePlacesModel = new KFilePlacesModel(this); setItemDelegate(new KFileItemDelegate(this)); setUniformRowHeights(true); // drag&drop setAcceptDrops(true); setDragEnabled(true); setDropIndicatorShown(true); mSourceModel->setDropsAllowed(KDirModel::DropOnDirectory); setStyle(new TreeStyle(style())); connect(this, &KrFileTreeView::activated, this, &KrFileTreeView::slotActivated); connect(mSourceModel, &KDirModel::expand, this, &KrFileTreeView::slotExpanded); QFontMetrics fontMetrics(viewport()->font()); header()->resizeSection(KDirModel::Name, fontMetrics.QFONTMETRICS_WIDTH("WWWWWWWWWWWWWWW")); header()->setContextMenuPolicy(Qt::CustomContextMenu); connect(header(), &QHeaderView::customContextMenuRequested, this, &KrFileTreeView::showHeaderContextMenu); setBriefMode(true); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &KrFileTreeView::customContextMenuRequested, this, &KrFileTreeView::slotCustomContextMenuRequested); setTree(mStartTreeFromCurrent, mStartTreeFromPlace); } void KrFileTreeView::setCurrentUrl(const QUrl &url) { mCurrentUrl = url; if (mStartTreeFromCurrent) { setTreeRoot(url); } else { if (mStartTreeFromPlace) { const QModelIndex index = mFilePlacesModel->closestItem(url); // magic here const QUrl rootBase = index.isValid() ? mFilePlacesModel->url(index) : QUrl::fromLocalFile(QDir::root().path()); setTreeRoot(rootBase); } if (isVisible(url)) { // avoid unwanted scrolling by KDirModel::expandToUrl() setCurrentIndex(mProxyModel->mapFromSource(mSourceModel->indexForUrl(url))); } else { mSourceModel->expandToUrl(url); } } } QUrl KrFileTreeView::urlForProxyIndex(const QModelIndex &index) const { const KFileItem item = mSourceModel->itemForIndex(mProxyModel->mapToSource(index)); return !item.isNull() ? item.url() : QUrl(); } void KrFileTreeView::slotActivated(const QModelIndex &index) { const QUrl url = urlForProxyIndex(index); if (url.isValid()) { emit urlActivated(url); } } void KrFileTreeView::dropEvent(QDropEvent *event) { QUrl destination = urlForProxyIndex(indexAt(event->pos())); if (destination.isEmpty()) { return; } FileSystemProvider::instance().startDropFiles(event, destination); } void KrFileTreeView::slotExpanded(const QModelIndex &baseIndex) { const QModelIndex index = mProxyModel->mapFromSource(baseIndex); expand(index); // expand view now after model was expanded selectionModel()->clearSelection(); selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent); scrollTo(index); } void KrFileTreeView::showHeaderContextMenu() { QMenu popup(this); popup.setToolTipsVisible(true); QAction *detailAction = popup.addAction(i18n("Show Details")); detailAction->setCheckable(true); detailAction->setChecked(!briefMode()); detailAction->setToolTip(i18n("Show columns with details")); QAction *showHiddenAction = popup.addAction(i18n("Show Hidden Folders")); showHiddenAction->setCheckable(true); showHiddenAction->setChecked(mSourceModel->dirLister()->showingDotFiles()); showHiddenAction->setToolTip(i18n("Show folders starting with a dot")); popup.addSeparator(); auto *rootActionGroup = new QActionGroup(this); QAction *startFromRootAction = popup.addAction(i18n("Start From Root")); startFromRootAction->setCheckable(true); startFromRootAction->setChecked(!mStartTreeFromCurrent && !mStartTreeFromPlace); startFromRootAction->setToolTip(i18n("Set root of the tree to root of filesystem")); startFromRootAction->setActionGroup(rootActionGroup); QAction *startFromCurrentAction = popup.addAction(i18n("Start From Current")); startFromCurrentAction->setCheckable(true); startFromCurrentAction->setChecked(mStartTreeFromCurrent); startFromCurrentAction->setToolTip(i18n("Set root of the tree to the current folder")); startFromCurrentAction->setActionGroup(rootActionGroup); QAction *startFromPlaceAction = popup.addAction(i18n("Start From Place")); startFromPlaceAction->setCheckable(true); startFromPlaceAction->setChecked(mStartTreeFromPlace); startFromPlaceAction->setToolTip( i18n("Set root of the tree to closest folder listed in 'Places'")); startFromPlaceAction->setActionGroup(rootActionGroup); QAction *triggeredAction = popup.exec(QCursor::pos()); if (triggeredAction == detailAction) { setBriefMode(!detailAction->isChecked()); } else if (triggeredAction == showHiddenAction) { KDirLister *dirLister = mSourceModel->dirLister(); dirLister->setShowingDotFiles(showHiddenAction->isChecked()); dirLister->emitChanges(); } else if (triggeredAction && triggeredAction->actionGroup() == rootActionGroup) { setTree(startFromCurrentAction->isChecked(), startFromPlaceAction->isChecked()); } } void KrFileTreeView::slotCustomContextMenuRequested(const QPoint &point) { const QModelIndex index = indexAt(point); if (!index.isValid()) return; const KFileItem fileItem = mSourceModel->itemForIndex(mProxyModel->mapToSource(index)); const KFileItemListProperties capabilities(KFileItemList() << fileItem); auto* popup = new QMenu(this); // TODO nice to have: "open with" // cut/copy/paste QAction* cutAction = new QAction(Icon(QStringLiteral("edit-cut")), i18nc("@action:inmenu", "Cut"), this); cutAction->setEnabled(capabilities.supportsMoving()); connect(cutAction, &QAction::triggered, this, [=]() { copyToClipBoard(fileItem, true); }); popup->addAction(cutAction); QAction* copyAction = new QAction(Icon(QStringLiteral("edit-copy")), i18nc("@action:inmenu", "Copy"), this); connect(copyAction, &QAction::triggered, this, [=]() { copyToClipBoard(fileItem, false); }); popup->addAction(copyAction); const QMimeData *mimeData = QApplication::clipboard()->mimeData(); bool canPaste; const QString text = KIO::pasteActionText(mimeData, &canPaste, fileItem); QAction* pasteAction = new QAction(Icon(QStringLiteral("edit-paste")), text, this); connect(pasteAction, &QAction::triggered, this, [=]() { KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), fileItem.url()); KJobWidgets::setWindow(job, this); }); pasteAction->setEnabled(canPaste); popup->addAction(pasteAction); popup->addSeparator(); // TODO nice to have: rename // trash if (KConfigGroup(krConfig, "General").readEntry("Move To Trash", _MoveToTrash)) { QAction* moveToTrashAction = new QAction(Icon(QStringLiteral("user-trash")), i18nc("@action:inmenu", "Move to Trash"), this); const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving(); moveToTrashAction->setEnabled(enableMoveToTrash); connect(moveToTrashAction, &QAction::triggered, this, [=]() { deleteFile(fileItem, true); }); popup->addAction(moveToTrashAction); } // delete QAction *deleteAction = new QAction(Icon(QStringLiteral("edit-delete")), i18nc("@action:inmenu", "Delete"), this); deleteAction->setEnabled(capabilities.supportsDeleting()); connect(deleteAction, &QAction::triggered, this, [=]() { deleteFile(fileItem, false); }); popup->addAction(deleteAction); popup->addSeparator(); // properties if (!fileItem.isNull()) { QAction* propertiesAction = new QAction(i18nc("@action:inmenu", "Properties"), this); propertiesAction->setIcon(Icon(QStringLiteral("document-properties"))); connect(propertiesAction, &QAction::triggered, this, [=]() { KPropertiesDialog* dialog = new KPropertiesDialog(fileItem.url(), this); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); }); popup->addAction(propertiesAction); } QPointer popupPtr = popup; popup->exec(QCursor::pos()); if (popupPtr.data()) { popupPtr.data()->deleteLater(); } } void KrFileTreeView::copyToClipBoard(const KFileItem &fileItem, bool cut) const { auto* mimeData = new QMimeData(); QList kdeUrls; kdeUrls.append(fileItem.url()); QList mostLocalUrls; bool dummy; mostLocalUrls.append(fileItem.mostLocalUrl(dummy)); KIO::setClipboardDataCut(mimeData, cut); KUrlMimeData::setUrls(kdeUrls, mostLocalUrls, mimeData); QApplication::clipboard()->setMimeData(mimeData); } void KrFileTreeView::deleteFile(const KFileItem &fileItem, bool moveToTrash) const { const QList confirmedFiles = ListPanelFunc::confirmDeletion(QList() << fileItem.url(), moveToTrash, false, true); if (confirmedFiles.isEmpty()) return; FileSystemProvider::instance().startDeleteFiles(confirmedFiles, moveToTrash); } bool KrFileTreeView::briefMode() const { return isColumnHidden(mProxyModel->columnCount() - 1); // find out by last column } void KrFileTreeView::setBriefMode(bool brief) { for (int i=1; i < mProxyModel->columnCount(); i++) { // show only first column setColumnHidden(i, brief); } } void KrFileTreeView::setTree(bool startFromCurrent, bool startFromPlace) { mStartTreeFromCurrent = startFromCurrent; mStartTreeFromPlace = startFromPlace; if (!mStartTreeFromCurrent && !mStartTreeFromPlace) { setTreeRoot(QUrl::fromLocalFile(QDir::root().path())); } setCurrentUrl(mCurrentUrl); // refresh } void KrFileTreeView::setTreeRoot(const QUrl &rootBase) { if (rootBase == mCurrentTreeBase) // avoid collapsing the subdirs in tree return; mCurrentTreeBase = rootBase; mSourceModel->dirLister()->openUrl(mCurrentTreeBase); } void KrFileTreeView::saveSettings(KConfigGroup cfg) const { KConfigGroup group = KConfigGroup(&cfg, "TreeView"); group.writeEntry("BriefMode", briefMode()); group.writeEntry("ShowHiddenFolders", mSourceModel->dirLister()->showingDotFiles()); group.writeEntry("StartFromCurrent", mStartTreeFromCurrent); group.writeEntry("StartFromPlace", mStartTreeFromPlace); } void KrFileTreeView::restoreSettings(const KConfigGroup &cfg) { const KConfigGroup group = KConfigGroup(&cfg, "TreeView"); setBriefMode(group.readEntry("BriefMode", true)); mSourceModel->dirLister()->setShowingDotFiles(group.readEntry("ShowHiddenFolders", false)); setTree(group.readEntry("StartFromCurrent", false), group.readEntry("StartFromPlace", false)); } bool KrFileTreeView::isVisible(const QUrl &url) { QModelIndex index = indexAt(rect().topLeft()); while (index.isValid()) { if (url == urlForProxyIndex(index)) { return true; } index = indexBelow(index); } return false; } diff --git a/krusader/Panel/krfiletreeview.h b/krusader/Panel/krfiletreeview.h index f779a45c..aa253639 100644 --- a/krusader/Panel/krfiletreeview.h +++ b/krusader/Panel/krfiletreeview.h @@ -1,89 +1,89 @@ /***************************************************************************** * Copyright (C) 2010 Jan Lepper * * Copyright (C) 2010-2019 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 KRFILETREEVIEW_H #define KRFILETREEVIEW_H #include #include #include #include #include #include #include #include #include /** * Show folders in a tree view. * * A context menu with settings is accessible through the header. * * Supports dragging from this view and dropping files on it. */ class KrFileTreeView : public QTreeView { friend class KrDirModel; Q_OBJECT public: explicit KrFileTreeView(QWidget *parent = nullptr); ~KrFileTreeView() override = default; void setCurrentUrl(const QUrl &url); void saveSettings(KConfigGroup cfg) const; void restoreSettings(const KConfigGroup &cfg); signals: void urlActivated(const QUrl &url); private slots: void slotActivated(const QModelIndex &index); void slotExpanded(const QModelIndex&); void showHeaderContextMenu(); void slotCustomContextMenuRequested(const QPoint &point); protected: - void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE; + void dropEvent(QDropEvent *event) override; private: QUrl urlForProxyIndex(const QModelIndex &index) const; void dropMimeData(const QList & lst, const QUrl &url) const; void copyToClipBoard(const KFileItem &fileItem, bool cut) const; void deleteFile(const KFileItem &fileItem, bool moveToTrash = true) const; bool briefMode() const; void setBriefMode(bool brief); // show only column with directory names void setTree(bool startFromCurrent, bool startFromPlace); void setTreeRoot(const QUrl &rootBase); bool isVisible(const QUrl &url); KDirModel *mSourceModel; KDirSortFilterProxyModel *mProxyModel; KFilePlacesModel *mFilePlacesModel; QUrl mCurrentUrl; QUrl mCurrentTreeBase; bool mStartTreeFromCurrent; // NAND... bool mStartTreeFromPlace; }; #endif // KRFILETREEVIEW_H diff --git a/krusader/Panel/krpreviewjob.h b/krusader/Panel/krpreviewjob.h index d5600ff7..c4c0bb79 100644 --- a/krusader/Panel/krpreviewjob.h +++ b/krusader/Panel/krpreviewjob.h @@ -1,66 +1,66 @@ /***************************************************************************** * Copyright (C) 2009 Jan Lepper * * Copyright (C) 2009-2019 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 KRPREVIEWJOB_H #define KRPREVIEWJOB_H // QtCore #include #include #include // QtGui #include #include #include class KrViewItem; class KrPreviews; class KrPreviewJob : public KJob { friend class KrPreviews; Q_OBJECT public: - void start() Q_DECL_OVERRIDE {} + void start() override {} protected slots: void slotStartJob(); void slotJobResult(KJob *job); void slotGotPreview(const KFileItem & item, const QPixmap & preview); void slotFailed(const KFileItem & item); protected: QList _scheduled; QHash _hash; KIO::PreviewJob *_job; QTimer _timer; KrPreviews *_parent; explicit KrPreviewJob(KrPreviews *parent); ~KrPreviewJob() override; void scheduleItem(KrViewItem *item); void removeItem(KrViewItem *item); void sort(); - bool doKill() Q_DECL_OVERRIDE; + bool doKill() override; }; #endif // __krpreviewjob__ diff --git a/krusader/Panel/krpreviewpopup.cpp b/krusader/Panel/krpreviewpopup.cpp index 00344622..5f58bb46 100644 --- a/krusader/Panel/krpreviewpopup.cpp +++ b/krusader/Panel/krpreviewpopup.cpp @@ -1,151 +1,151 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 "krpreviewpopup.h" #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include "../KViewer/krviewer.h" class KrPreviewPopup::ProxyStyle : public QProxyStyle { public: ProxyStyle() : QProxyStyle(QApplication::style()) {} QSize sizeFromContents(ContentsType type, const QStyleOption *option, - const QSize &contentsSize, const QWidget *widget = nullptr) const Q_DECL_OVERRIDE + const QSize &contentsSize, const QWidget *widget = nullptr) const override { if(type == QStyle::CT_MenuItem) { const auto *menuItem = qstyleoption_cast(option); QFontMetrics fontMetrics(menuItem->font); QSize iconSize = menuItem->icon.actualSize(QSize(MAX_SIZE, MAX_SIZE)); QSize textSize = QSize(fontMetrics.boundingRect(menuItem->text).width(), fontMetrics.height()); return QSize(std::max(iconSize.width(), textSize.width()) + MARGIN*2, iconSize.height() + textSize.height() + MARGIN*2); } else return QProxyStyle::sizeFromContents(type, option, contentsSize, widget); } void drawControl(ControlElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget = nullptr ) const Q_DECL_OVERRIDE + QPainter *painter, const QWidget *widget = nullptr ) const override { if(element == QStyle::CE_MenuItem) { painter->save(); const auto *menuItem = qstyleoption_cast(option); bool active = menuItem->state & State_Selected; QRect rect = menuItem->rect; if(active) painter->fillRect(rect, menuItem->palette.brush(QPalette::Highlight)); rect.adjust(MARGIN, MARGIN, -MARGIN, -MARGIN); int textHeight = QFontMetrics(menuItem->font).height(); QRect previewRect = rect; previewRect.setHeight(rect.height() - textHeight); QPixmap pixmap = menuItem->icon.pixmap(menuItem->icon.actualSize(QSize(MAX_SIZE, MAX_SIZE))); QProxyStyle::drawItemPixmap(painter, previewRect, Qt::AlignCenter, pixmap); QRect textRect = rect; textRect.setTop(previewRect.bottom() + 1); painter->setPen(active ? menuItem->palette.highlightedText().color() : menuItem->palette.buttonText().color()); int textFlags = Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignCenter; painter->drawText(textRect, textFlags, menuItem->text); painter->restore(); } else QProxyStyle::drawControl(element, option, painter, widget); } }; KrPreviewPopup::KrPreviewPopup() : jobStarted(false) { prevNotAvailAction = addAction(i18n("Preview not available")); setStyle(new ProxyStyle()); connect(this, &KrPreviewPopup::triggered, this, &KrPreviewPopup::view); } void KrPreviewPopup::showEvent(QShowEvent *event) { QMenu::showEvent(event); if (!jobStarted) { QStringList allPlugins = KIO::PreviewJob::availablePlugins(); KIO::PreviewJob *pjob = new KIO::PreviewJob(files, QSize(MAX_SIZE, MAX_SIZE), &allPlugins); pjob->setOverlayIconSize(0); pjob->setOverlayIconAlpha(1); pjob->setScaleType(KIO::PreviewJob::ScaledAndCached); connect(pjob, &KIO::PreviewJob::gotPreview, this, &KrPreviewPopup::addPreview); jobStarted = true; } } void KrPreviewPopup::setUrls(const QList &urls) { foreach(const QUrl &url, urls) { files.push_back(KFileItem(url)); } } void KrPreviewPopup::addPreview(const KFileItem& file, const QPixmap& preview) { if (prevNotAvailAction) { removeAction(prevNotAvailAction); delete prevNotAvailAction; prevNotAvailAction = nullptr; } QAction *act = addAction(file.text()); act->setIcon(QIcon(preview)); act->setData(QVariant::fromValue(file.url())); } void KrPreviewPopup::view(QAction *clicked) { if (clicked && clicked->data().canConvert()) KrViewer::view(clicked->data().value()); } diff --git a/krusader/Panel/krpreviewpopup.h b/krusader/Panel/krpreviewpopup.h index e87ec9ae..f050f26d 100644 --- a/krusader/Panel/krpreviewpopup.h +++ b/krusader/Panel/krpreviewpopup.h @@ -1,60 +1,60 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 KRPREVIEWPOPUP_H #define KRPREVIEWPOPUP_H // QtCore #include // QtGui #include // QtWidgets #include #include class KrPreviewPopup : public QMenu { Q_OBJECT public: KrPreviewPopup(); void setUrls(const QList &urls); public slots: void addPreview(const KFileItem& file, const QPixmap& preview); void view(QAction *); protected: - void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *event) override; QAction * prevNotAvailAction; QList files; bool jobStarted; private: static const int MAX_SIZE =400; static const short MARGIN =5; class ProxyStyle; }; #endif diff --git a/krusader/Panel/krsearchbar.h b/krusader/Panel/krsearchbar.h index b955a308..7a972159 100644 --- a/krusader/Panel/krsearchbar.h +++ b/krusader/Panel/krsearchbar.h @@ -1,115 +1,115 @@ /***************************************************************************** * Copyright (C) 2010 Jan Lepper * * Copyright (C) 2010-2019 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 KRSEARCHBAR_H #define KRSEARCHBAR_H #include #include #include #include class KrView; /** * @brief Search, select or filter files by search string * * The search bar can be used in three different modes: * search: cursor jumpes with up/down arrow keys to previous/next matching file * select: all files in model matching an expression are selected * filter: all files in model not matching an expression are filtered (hidden) * * These actions are implemented in KrView and KrViewOperator. * * NOTE: some key events in KrView are filtered here. */ class KrSearchBar : public QWidget { Q_OBJECT public: enum SearchMode { MODE_DEFAULT = -1, // NOTE: values used for combobox index MODE_SEARCH = 0, MODE_SELECT = 1, MODE_FILTER = 2, }; public: KrSearchBar(KrView *view, QWidget *parent); /** * Set another KrView, old one must not be deleted yet! */ void setView(KrView *view); /** * Hide the search bar if its mode was the search one. * * This function is normally used to hide bar after a user has quicksearched for something and found it. */ void hideBarIfSearching(); public slots: void showBar(SearchMode mode = MODE_DEFAULT); void hideBar(); /** * Reset search to empty string. */ void resetSearch(); protected slots: void onModeChange(); void onSearchChange(); /** * Save current search string to settings */ void saveSearchString(); protected: - void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *) override; /** * Filter key events from view widget and text combo box */ - bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE; + bool eventFilter(QObject *, QEvent *) override; private: /** * Handle events when search bar is open or open it. */ bool handleKeyPressEvent(QKeyEvent *ke); bool handleUpDownKeyPress(bool); bool handleLeftRightKeyPress(QKeyEvent *ke); /** * Set color of line edit to highlight if anything matches. */ void indicateMatch(bool); static bool caseSensitive(); private: KrView *_view; QComboBox *_modeBox; KComboBox *_textBox; QToolButton *_openSelectDialogBtn; SearchMode _currentMode; bool _rightArrowEntersDirFlag; }; #endif // KRSEARCHBAR_H diff --git a/krusader/Panel/listpanel.cpp b/krusader/Panel/listpanel.cpp index 159ad4c7..515a6f71 100644 --- a/krusader/Panel/listpanel.cpp +++ b/krusader/Panel/listpanel.cpp @@ -1,1376 +1,1376 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 "listpanel.h" // QtCore #include #include #include #include #include #include #include // QtGui #include #include #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dirhistoryqueue.h" #include "krcolorcache.h" #include "krerrordisplay.h" #include "krlayoutfactory.h" #include "krpreviewpopup.h" #include "krsearchbar.h" #include "listpanelactions.h" #include "panelcontextmenu.h" #include "panelfunc.h" #include "sidebar.h" #include "viewactions.h" #include "PanelView/krview.h" #include "PanelView/krviewfactory.h" #include "PanelView/krviewitem.h" #include "../defaults.h" #include "../icon.h" #include "../krservices.h" #include "../krslots.h" #include "../krusader.h" #include "../krusaderview.h" #include "../Archive/krarchandler.h" #include "../BookMan/krbookmarkbutton.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/filesystem.h" #include "../FileSystem/krpermhandler.h" #include "../FileSystem/sizecalculator.h" #include "../Dialogs/krdialogs.h" #include "../Dialogs/krspwidgets.h" #include "../Dialogs/krsqueezedtextlabel.h" #include "../Dialogs/percentalsplitter.h" #include "../Dialogs/popularurls.h" #include "../GUI/dirhistorybutton.h" #include "../GUI/kcmdline.h" #include "../GUI/mediabutton.h" #include "../MountMan/kmountman.h" #include "../UserAction/useractionpopupmenu.h" class ActionButton : public QToolButton { public: ActionButton(QWidget *parent, ListPanel *panel, QAction *action, const QString& text = QString()) : QToolButton(parent), panel(panel), action(action) { setText(text); setAutoRaise(true); if(KConfigGroup(krConfig, "ListPanelButtons").readEntry("Icons", false) || text.isEmpty()) setIcon(action->icon()); setToolTip(action->toolTip()); } protected: - void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE { + void mousePressEvent(QMouseEvent *) override { panel->slotFocusOnMe(); action->trigger(); } ListPanel *panel; QAction *action; }; ///////////////////////////////////////////////////// // The list panel constructor // ///////////////////////////////////////////////////// ListPanel::ListPanel(QWidget *parent, AbstractPanelManager *manager, const KConfigGroup &cfg) : QWidget(parent), KrPanel(manager, this, new ListPanelFunc(this)), panelType(-1), colorMask(255), compareMode(false), previewJob(nullptr), inlineRefreshJob(nullptr), searchBar(nullptr), cdRootButton(nullptr), cdUpButton(nullptr), sidebarButton(nullptr), sidebar(nullptr), fileSystemError(nullptr), _tabState(TabState::DEFAULT) { if(cfg.isValid()) panelType = cfg.readEntry("Type", -1); if (panelType == -1) panelType = defaultPanelType(); _actions = krApp->listPanelActions(); setAcceptDrops(true); QHash widgets; #define ADD_WIDGET(widget) widgets.insert(#widget, widget); // media button mediaButton = new MediaButton(this); connect(mediaButton, &MediaButton::aboutToShow, this, [=]() { slotFocusOnMe(); }); connect(mediaButton, &MediaButton::openUrl, [=](const QUrl & _t1) { func->openUrl(_t1); }); connect(mediaButton, &MediaButton::newTab, this, [=](const QUrl &url) { newTab(url); }); ADD_WIDGET(mediaButton); // status bar status = new KrSqueezedTextLabel(this); KConfigGroup group(krConfig, "Look&Feel"); status->setFont(group.readEntry("Filelist Font", _FilelistFont)); status->setAutoFillBackground(false); status->setText(""); // needed for initialization code! status->setWhatsThis(i18n("The statusbar displays information about the filesystem " "which holds your current folder: total size, free space, " "type of filesystem, etc.")); ADD_WIDGET(status); // back button backButton = new ActionButton(this, this, _actions->actHistoryBackward); ADD_WIDGET(backButton); // forward button forwardButton = new ActionButton(this, this, _actions->actHistoryForward); ADD_WIDGET(forwardButton); // ... create the history button historyButton = new DirHistoryButton(func->history, this); connect(historyButton, &DirHistoryButton::aboutToShow, this, [=]() { slotFocusOnMe(); }); connect(historyButton, &DirHistoryButton::gotoPos, func, &ListPanelFunc::historyGotoPos); ADD_WIDGET(historyButton); // bookmarks button bookmarksButton = new KrBookmarkButton(this); connect(bookmarksButton, &KrBookmarkButton::aboutToShow, this, [=]() { slotFocusOnMe(); }); connect(bookmarksButton, &KrBookmarkButton::openUrl, [=](const QUrl & _t1) { func->openUrl(_t1); }); bookmarksButton->setWhatsThis(i18n("Open menu with bookmarks. You can also add " "current location to the list, edit bookmarks " "or add subfolder to the list.")); ADD_WIDGET(bookmarksButton); // url input field urlNavigator = new KUrlNavigator(new KFilePlacesModel(this), QUrl(), this); urlNavigator->setWhatsThis(i18n("Name of folder where you are. You can also " "enter name of desired location to move there. " "Use of Net protocols like ftp or fish is possible.")); // handle certain key events here in event filter urlNavigator->editor()->installEventFilter(this); urlNavigator->setUrlEditable(isNavigatorEditModeSet()); urlNavigator->setShowFullPath(group.readEntry("Navigator Full Path", false)); connect(urlNavigator, &KUrlNavigator::returnPressed, this, [=]() { slotFocusOnMe(); }); connect(urlNavigator, &KUrlNavigator::urlChanged, this, &ListPanel::slotNavigatorUrlChanged); connect(urlNavigator->editor()->lineEdit(), &QLineEdit::editingFinished, this, &ListPanel::resetNavigatorMode); connect(urlNavigator, &KUrlNavigator::tabRequested, this, [=](const QUrl &url) { ListPanel::newTab(url); }); connect(urlNavigator, &KUrlNavigator::urlsDropped, this, QOverload::of(&ListPanel::handleDrop)); ADD_WIDGET(urlNavigator); // toolbar QWidget * toolbar = new QWidget(this); auto * toolbarLayout = new QHBoxLayout(toolbar); toolbarLayout->setContentsMargins(0, 0, 0, 0); toolbarLayout->setSpacing(0); ADD_WIDGET(toolbar); fileSystemError = new KrErrorDisplay(this); fileSystemError->setWordWrap(true); fileSystemError->hide(); ADD_WIDGET(fileSystemError); // client area clientArea = new QWidget(this); auto *clientLayout = new QVBoxLayout(clientArea); clientLayout->setSpacing(0); clientLayout->setContentsMargins(0, 0, 0, 0); ADD_WIDGET(clientArea); // totals label totals = new KrSqueezedTextLabel(this); totals->setFont(group.readEntry("Filelist Font", _FilelistFont)); totals->setAutoFillBackground(false); totals->setWhatsThis(i18n("The totals bar shows how many files exist, " "how many selected and the bytes math")); ADD_WIDGET(totals); // free space label freeSpace = new KrSqueezedTextLabel(this); freeSpace->setFont(group.readEntry("Filelist Font", _FilelistFont)); freeSpace->setAutoFillBackground(false); freeSpace->setText(""); freeSpace->setAlignment(Qt::AlignRight | Qt::AlignVCenter); ADD_WIDGET(freeSpace); // progress indicator and cancel button for the quick calc size quickSizeCalcProgress = new QProgressBar(this); quickSizeCalcProgress->hide(); ADD_WIDGET(quickSizeCalcProgress); cancelQuickSizeCalcButton = new QToolButton(this); cancelQuickSizeCalcButton->hide(); cancelQuickSizeCalcButton->setIcon(Icon("dialog-cancel")); cancelQuickSizeCalcButton->setToolTip(i18n("Cancel directory space calculation")); ADD_WIDGET(cancelQuickSizeCalcButton); // progress indicator for the preview job previewProgress = new QProgressBar(this); previewProgress->hide(); ADD_WIDGET(previewProgress); // a cancel button for the filesystem refresh and preview job cancelProgressButton = new QToolButton(this); cancelProgressButton->hide(); cancelProgressButton->setIcon(Icon("dialog-cancel")); connect(cancelProgressButton, &QToolButton::clicked, this, &ListPanel::cancelProgress); ADD_WIDGET(cancelProgressButton); // button for changing the panel sidebar position in the panel sidebarPositionButton = new QToolButton(this); sidebarPositionButton->hide(); sidebarPositionButton->setAutoRaise(true); sidebarPositionButton->setIcon(Icon("exchange-positions")); sidebarPositionButton->setToolTip(i18n("Move Sidebar clockwise")); connect(sidebarPositionButton, &QToolButton::clicked, [this]() { // moving position clockwise setSidebarPosition((sidebarPosition() + 1) % 4); }); ADD_WIDGET(sidebarPositionButton); // a quick button to open the sidebar sidebarButton = new QToolButton(this); sidebarButton->setAutoRaise(true); sidebarButton->setIcon(Icon("arrow-up")); connect(sidebarButton, &QToolButton::clicked, this, &ListPanel::toggleSidebar); sidebarButton->setToolTip(i18n("Open the Sidebar")); ADD_WIDGET(sidebarButton); #undef ADD_WIDGET // toolbar buttons cdOtherButton = new ActionButton(toolbar, this, _actions->actCdToOther, "="); toolbarLayout->addWidget(cdOtherButton); cdUpButton = new ActionButton(toolbar, this, _actions->actDirUp, ".."); toolbarLayout->addWidget(cdUpButton); cdHomeButton = new ActionButton(toolbar, this, _actions->actHome, "~"); toolbarLayout->addWidget(cdHomeButton); cdRootButton = new ActionButton(toolbar, this, _actions->actRoot, "/"); toolbarLayout->addWidget(cdRootButton); // create the button for sync-browsing syncBrowseButton = new QToolButton(toolbar); syncBrowseButton->setIcon(Icon("kr_syncbrowse_off")); syncBrowseButton->setCheckable(true); const QString syncBrowseText = i18n("This button toggles the sync-browse mode.\n" "When active, each folder change is performed in the\n" "active and inactive panel - if possible."); syncBrowseButton->setText(syncBrowseText); syncBrowseButton->setToolTip(syncBrowseText); connect(syncBrowseButton, &QToolButton::toggled, [=](bool checked) { syncBrowseButton->setIcon( Icon(checked ? "kr_syncbrowse_on" : "kr_syncbrowse_off")); }); syncBrowseButton->setAutoRaise(true); toolbarLayout->addWidget(syncBrowseButton); setButtons(); // create a splitter to hold the view and the sidebar sidebarSplitter = new PercentalSplitter(clientArea); sidebarSplitter->setChildrenCollapsible(true); sidebarSplitter->setOrientation(Qt::Horizontal); // expand vertical if splitter orientation is horizontal QSizePolicy sizePolicy = sidebarSplitter->sizePolicy(); sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); sidebarSplitter->setSizePolicy(sizePolicy); clientLayout->addWidget(sidebarSplitter); // view createView(); // search (in folder) bar searchBar = new KrSearchBar(view, clientArea); searchBar->hide(); bool top = group.readEntry("Quicksearch Position", "bottom") == "top"; clientLayout->insertWidget(top ? 0 : -1, searchBar); // create the layout KrLayoutFactory fact(this, widgets); QLayout *layout = fact.createLayout(); if(!layout) { // fallback: create a layout by ourself auto *v = new QVBoxLayout; v->setContentsMargins(0, 0, 0, 0); v->setSpacing(0); auto *h = new QHBoxLayout; h->setContentsMargins(0, 0, 0, 0); h->setSpacing(0); h->addWidget(urlNavigator); h->addWidget(toolbar); h->addStretch(); v->addLayout(h); h = new QHBoxLayout; h->setContentsMargins(0, 0, 0, 0); h->setSpacing(0); h->addWidget(mediaButton); h->addWidget(status); h->addWidget(backButton); h->addWidget(forwardButton); h->addWidget(historyButton); h->addWidget(bookmarksButton); v->addLayout(h); v->addWidget(fileSystemError); v->addWidget(clientArea); h = new QHBoxLayout; h->setContentsMargins(0, 0, 0, 0); h->setSpacing(0); h->addWidget(totals); h->addWidget(freeSpace); h->addWidget(quickSizeCalcProgress); h->addWidget(cancelQuickSizeCalcButton); h->addWidget(previewProgress); h->addWidget(cancelProgressButton); h->addWidget(sidebarButton); v->addLayout(h); layout = v; } setLayout(layout); connect(&KrColorCache::getColorCache(), &KrColorCache::colorsRefreshed, this, &ListPanel::slotRefreshColors); connect(krApp, &Krusader::shutdown, this, &ListPanel::cancelProgress); } ListPanel::~ListPanel() { cancelProgress(); delete view; view = nullptr; delete func; delete status; delete bookmarksButton; delete totals; delete urlNavigator; delete cdRootButton; delete cdHomeButton; delete cdUpButton; delete cdOtherButton; delete syncBrowseButton; // delete layout; } void ListPanel::reparent(QWidget *parent, AbstractPanelManager *manager) { setParent(parent); _manager = manager; } int ListPanel::defaultPanelType() { KConfigGroup group(krConfig, "Look&Feel"); return group.readEntry("Default Panel Type", KrViewFactory::defaultViewId()); } bool ListPanel::isNavigatorEditModeSet() { KConfigGroup group(krConfig, "Look&Feel"); return group.readEntry("Navigator Edit Mode", false); } void ListPanel::createView() { view = KrViewFactory::createView(panelType, sidebarSplitter, krConfig); view->init(); view->setMainWindow(krApp); // KrViewFactory may create a different view type than requested panelType = view->instance()->id(); if(this == ACTIVE_PANEL) view->prepareForActive(); else view->prepareForPassive(); view->refreshColors(); sidebarSplitter->insertWidget(sidebarPosition() < 2 ? 1 : 0, view->widget()); view->widget()->installEventFilter(this); connect(view->op(), &KrViewOperator::quickCalcSpace, func, &ListPanelFunc::quickCalcSpace); connect(view->op(), &KrViewOperator::goHome, func, &ListPanelFunc::home); connect(view->op(), &KrViewOperator::dirUp, func, &ListPanelFunc::dirUp); connect(view->op(), &KrViewOperator::defaultDeleteFiles, func, &ListPanelFunc::defaultDeleteFiles); connect(view->op(), &KrViewOperator::middleButtonClicked, this, QOverload::of(&ListPanel::newTab)); connect(view->op(), &KrViewOperator::currentChanged, this, &ListPanel::slotCurrentChanged); connect(view->op(), &KrViewOperator::renameItem, func, QOverload::of(&ListPanelFunc::rename)); connect(view->op(), &KrViewOperator::executed, func, &ListPanelFunc::execute); connect(view->op(), &KrViewOperator::goInside, func, &ListPanelFunc::goInside); connect(view->op(), &KrViewOperator::needFocus, this, [=]() { slotFocusOnMe(); }); connect(view->op(), &KrViewOperator::selectionChanged, this, &ListPanel::slotUpdateTotals); connect(view->op(), &KrViewOperator::itemDescription, krApp, &Krusader::statusBarUpdate); connect(view->op(), &KrViewOperator::contextMenu, this, &ListPanel::popRightClickMenu); connect(view->op(), &KrViewOperator::emptyContextMenu, this, &ListPanel::popEmptyRightClickMenu); connect(view->op(), &KrViewOperator::letsDrag, this, &ListPanel::startDragging); connect(view->op(), &KrViewOperator::gotDrop, this, [this](QDropEvent *event) {handleDrop(event, true); }); connect(view->op(), &KrViewOperator::previewJobStarted, this, &ListPanel::slotPreviewJobStarted); connect(view->op(), &KrViewOperator::refreshActions, krApp->viewActions(), &ViewActions::refreshActions); connect(view->op(), &KrViewOperator::currentChanged, func->history, &DirHistoryQueue::saveCurrentItem); connect(view->op(), &KrViewOperator::goBack, func, &ListPanelFunc::historyBackward); connect(view->op(), &KrViewOperator::goForward, func, &ListPanelFunc::historyForward); view->setFiles(func->files()); func->refreshActions(); } void ListPanel::changeType(int type) { if (panelType != type) { QString current = view->getCurrentItem(); QList selection = view->selectedUrls(); bool filterApplysToDirs = view->properties()->filterApplysToDirs; KrViewProperties::FilterSpec filter = view->filter(); FilterSettings filterSettings = view->properties()->filterSettings; panelType = type; KrView *oldView = view; createView(); searchBar->setView(view); delete oldView; view->setFilter(filter, filterSettings, filterApplysToDirs); view->setSelectionUrls(selection); view->setCurrentItem(current); view->makeItemVisible(view->getCurrentKrViewItem()); } } int ListPanel::getProperties() { int props = 0; if (syncBrowseButton->isChecked()) { props |= PROP_SYNC_BUTTON_ON; } if (isLocked()) { props |= PROP_LOCKED; } else if (isPinned()) { props |= PROP_PINNED; } return props; } void ListPanel::setProperties(int prop) { syncBrowseButton->setChecked(prop & PROP_SYNC_BUTTON_ON); if (prop & PROP_LOCKED) { _tabState = TabState::LOCKED; } else if (prop & PROP_PINNED) { _tabState = TabState::PINNED; } else { _tabState = TabState::DEFAULT; } } bool ListPanel::eventFilter(QObject * watched, QEvent * e) { if(view && watched == view->widget()) { if(e->type() == QEvent::FocusIn && this != ACTIVE_PANEL && !isHidden()) slotFocusOnMe(); else if(e->type() == QEvent::ShortcutOverride) { auto *ke = dynamic_cast(e); if(ke->key() == Qt::Key_Escape && ke->modifiers() == Qt::NoModifier) { // if the cancel refresh action has no shortcut assigned, // we need this event ourselves to cancel refresh if(_actions->actCancelRefresh->shortcut().isEmpty()) { e->accept(); return true; } } } } // handle URL navigator key events else if(watched == urlNavigator->editor()) { // override default shortcut for panel focus if(e->type() == QEvent::ShortcutOverride) { auto *ke = dynamic_cast(e); if ((ke->key() == Qt::Key_Escape) && (ke->modifiers() == Qt::NoModifier)) { e->accept(); // we will get the key press event now return true; } } else if(e->type() == QEvent::KeyPress) { auto *ke = dynamic_cast(e); if ((ke->key() == Qt::Key_Down) && (ke->modifiers() == Qt::ControlModifier)) { slotFocusOnMe(); return true; } else if ((ke->key() == Qt::Key_Escape) && (ke->modifiers() == Qt::NoModifier)) { // reset navigator urlNavigator->editor()->setUrl(urlNavigator->locationUrl()); slotFocusOnMe(); return true; } } } return false; } void ListPanel::toggleSidebar() { if(!sidebar) { sidebar = new Sidebar(sidebarSplitter); // fix vertical grow of splitter (and entire window) if its content // demands more space QSizePolicy sizePolicy = sidebar->sizePolicy(); sizePolicy.setVerticalPolicy(QSizePolicy::Ignored); sidebar->setSizePolicy(sizePolicy); connect(this, &ListPanel::pathChanged, sidebar, &Sidebar::onPanelPathChange); connect(sidebar, &Sidebar::urlActivated, SLOTS, &KRslots::refresh); sidebarSplitter->insertWidget(0, sidebar); } if (sidebar->isHidden()) { if (sidebarSplitterSizes.count() > 0) { sidebarSplitter->setSizes(sidebarSplitterSizes); } else { // on the first time, resize to 50% QList lst; lst << height() / 2 << height() / 2; sidebarSplitter->setSizes(lst); } sidebar->show(); sidebarButton->setIcon(Icon("arrow-down")); sidebarButton->setToolTip(i18n("Close the Sidebar")); sidebarPositionButton->show(); } else { sidebarSplitterSizes.clear(); sidebarSplitterSizes = sidebarSplitter->sizes(); sidebar->hide(); sidebarButton->setIcon(Icon("arrow-up")); sidebarButton->setToolTip(i18n("Open the Sidebar")); sidebarPositionButton->hide(); QList lst; lst << height() << 0; sidebarSplitter->setSizes(lst); if (ACTIVE_PANEL) ACTIVE_PANEL->gui->slotFocusOnMe(); } } QString ListPanel::lastLocalPath() const { return _lastLocalPath; } void ListPanel::setButtons() { KConfigGroup group(krConfig, "Look&Feel"); mediaButton->setVisible(group.readEntry("Media Button Visible", true)); backButton->setVisible(group.readEntry("Back Button Visible", false)); forwardButton->setVisible(group.readEntry("Forward Button Visible", false)); historyButton->setVisible(group.readEntry("History Button Visible", true)); bookmarksButton->setVisible(group.readEntry("Bookmarks Button Visible", true)); if (group.readEntry("Panel Toolbar visible", _PanelToolBar)) { cdRootButton->setVisible(group.readEntry("Root Button Visible", _cdRoot)); cdHomeButton->setVisible(group.readEntry("Home Button Visible", _cdHome)); cdUpButton->setVisible(group.readEntry("Up Button Visible", _cdUp)); cdOtherButton->setVisible(group.readEntry("Equal Button Visible", _cdOther)); syncBrowseButton->setVisible(group.readEntry("SyncBrowse Button Visible", _syncBrowseButton)); } else { cdRootButton->hide(); cdHomeButton->hide(); cdUpButton->hide(); cdOtherButton->hide(); syncBrowseButton->hide(); } } void ListPanel::slotUpdateTotals() { totals->setText(view->statistics()); } void ListPanel::compareDirs(bool otherPanelToo) { // Performs a check in order to avoid that the next code is executed twice if (otherPanelToo == true) { // If both panels are showing the same directory if (_manager->currentPanel()->virtualPath() == otherPanel()->virtualPath()) { if (KMessageBox::warningContinueCancel(this, i18n("Warning: The left and the right side are showing the same folder.")) != KMessageBox::Continue) { return; } } } KConfigGroup pg(krConfig, "Private"); int compareMode = pg.readEntry("Compare Mode", 0); KConfigGroup group(krConfig, "Look&Feel"); bool selectDirs = group.readEntry("Mark Dirs", false); KrViewItem *item, *otherItem; for (item = view->getFirst(); item != nullptr; item = view->getNext(item)) { if (item->name() == "..") continue; for (otherItem = otherPanel()->view->getFirst(); otherItem != nullptr && otherItem->name() != item->name(); otherItem = otherPanel()->view->getNext(otherItem)); bool isSingle = (otherItem == nullptr), isDifferent = false, isNewer = false; if (func->getFileItem(item)->isDir() && !selectDirs) { item->setSelected(false); continue; } if (otherItem) { if (!func->getFileItem(item)->isDir()) isDifferent = otherPanel()->func->getFileItem(otherItem)->getSize() != func->getFileItem(item)->getSize(); isNewer = func->getFileItem(item)->getModificationTime() > otherPanel()->func->getFileItem(otherItem)->getModificationTime(); } switch (compareMode) { case 0: item->setSelected(isNewer || isSingle); break; case 1: item->setSelected(isNewer); break; case 2: item->setSelected(isSingle); break; case 3: item->setSelected(isDifferent || isSingle); break; case 4: item->setSelected(isDifferent); break; } } view->updateView(); if (otherPanelToo) otherPanel()->gui->compareDirs(false); } void ListPanel::slotRefreshColors() { view->refreshColors(); emit signalRefreshColors(this == ACTIVE_PANEL); } void ListPanel::slotFocusOnMe(bool focus) { if (focus && _manager->currentPanel() != this) { // ignore focus request if this panel is not shown return; } krApp->setUpdatesEnabled(false); if(focus) { emit activate(); _actions->activePanelChanged(); func->refreshActions(); slotCurrentChanged(view->getCurrentKrViewItem()); view->prepareForActive(); otherPanel()->gui->slotFocusOnMe(false); } else { // in case a new url was entered but not refreshed to, // reset url navigator to the current url setNavigatorUrl(virtualPath()); view->prepareForPassive(); } urlNavigator->setActive(focus); slotRefreshColors(); krApp->setUpdatesEnabled(true); } // this is used to start the panel ////////////////////////////////////////////////////////////////// void ListPanel::start(const QUrl &url) { QUrl startUrl(url); if (!startUrl.isValid()) startUrl = QUrl::fromLocalFile(ROOT_DIR); _lastLocalPath = startUrl.isLocalFile() ? startUrl.path() : ROOT_DIR; func->openUrl(startUrl); setJumpBack(startUrl); } void ListPanel::slotStartUpdate(bool directoryChange) { if (inlineRefreshJob) inlineRefreshListResult(nullptr); setCursor(Qt::BusyCursor); const QUrl currentUrl = virtualPath(); if (directoryChange) { if (this == ACTIVE_PANEL) { slotFocusOnMe(); } if (currentUrl.isLocalFile()) _lastLocalPath = currentUrl.path(); setNavigatorUrl(currentUrl); emit pathChanged(currentUrl); krApp->popularUrls()->addUrl(currentUrl); searchBar->hideBar(); } if (compareMode) otherPanel()->view->refresh(); // return cursor to normal arrow setCursor(Qt::ArrowCursor); slotUpdateTotals(); } void ListPanel::updateFilesystemStats(const QString &metaInfo, const QString &fsType, KIO::filesize_t total, KIO::filesize_t free) { QString statusText, mountPoint, freeSpaceText; if (!metaInfo.isEmpty()) { statusText = metaInfo; mountPoint = freeSpaceText = ""; } else { const int perc = total == 0 ? 0 : (int)(((float)free / (float)total) * 100.0); mountPoint = func->files()->mountPoint(); statusText = i18nc("%1=free space,%2=total space,%3=percentage of usage, " "%4=mountpoint,%5=filesystem type", "%1 free out of %2 (%3%) on %4 [(%5)]", KIO::convertSize(free), KIO::convertSize(total), perc, mountPoint, fsType); freeSpaceText = " " + i18n("%1 free", KIO::convertSize(free)); } status->setText(statusText); freeSpace->setText(freeSpaceText); mediaButton->updateIcon(mountPoint); } void ListPanel::handleDrop(QDropEvent *event, bool onView) { // check what was dropped const QList urls = KUrlMimeData::urlsFromMimeData(event->mimeData()); if (urls.isEmpty()) { event->ignore(); // not for us to handle! return; } // find dropping destination QString destinationDir = ""; const bool dragFromThisPanel = event->source() == this; const KrViewItem *item = onView ? view->getKrViewItemAt(event->pos()) : nullptr; if (item) { const FileItem *file = item->getFileItem(); if (file && !file->isDir() && dragFromThisPanel) { event->ignore(); // dragging on files in same panel, ignore return; } else if (!file || file->isDir()) { // item is ".." dummy or a directory destinationDir = item->name(); } } else if (dragFromThisPanel) { event->ignore(); // dragged from this panel onto an empty spot in this panel, ignore return; } QUrl destination = QUrl(virtualPath()); destination.setPath(destination.path() + '/' + destinationDir); func->files()->dropFiles(destination, event); if(KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { KrPanel *p = dragFromThisPanel ? this : otherPanel(); p->view->saveSelection(); p->view->unselectAll(); } } void ListPanel::handleDrop(const QUrl &destination, QDropEvent *event) { func->files()->dropFiles(destination, event); } void ListPanel::startDragging(const QStringList& names, const QPixmap& px) { if (names.isEmpty()) { // avoid dragging empty urls return; } QList urls = func->files()->getUrls(names); auto *drag = new QDrag(this); auto *mimeData = new QMimeData; drag->setPixmap(px); mimeData->setUrls(urls); drag->setMimeData(mimeData); drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction); } // pops a right-click menu for items void ListPanel::popRightClickMenu(const QPoint &loc) { // run it, on the mouse location int j = QFontMetrics(font()).height() * 2; PanelContextMenu::run(QPoint(loc.x() + 5, loc.y() + j), this); } void ListPanel::popEmptyRightClickMenu(const QPoint &loc) { PanelContextMenu::run(loc, this); } QString ListPanel::getCurrentName() const { const QString name = view->getCurrentItem(); return name == ".." ? QString() : name; } QStringList ListPanel::getSelectedNames() { QStringList fileNames; view->getSelectedItems(&fileNames); return fileNames; } void ListPanel::prepareToDelete() { const bool skipCurrent = (view->numSelected() == 0); view->setNameToMakeCurrent(view->firstUnmarkedBelowCurrent(skipCurrent)); } void ListPanel::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Enter : case Qt::Key_Return : if (e->modifiers() & Qt::ControlModifier) { if (e->modifiers() & Qt::AltModifier) { FileItem *fileitem = func->files()->getFileItem(view->getCurrentKrViewItem()->name()); if (fileitem && fileitem->isDir()) newTab(fileitem->getUrl(), true); } else { SLOTS->insertFileName((e->modifiers()&Qt::ShiftModifier)!=0); } } else { e->ignore(); } break; case Qt::Key_Right : case Qt::Key_Left : if (e->modifiers() == Qt::ControlModifier) { // user pressed CTRL+Right/Left - refresh other panel to the selected path if it's a // directory otherwise as this one if ((isLeft() && e->key() == Qt::Key_Right) || (!isLeft() && e->key() == Qt::Key_Left)) { QUrl newPath; KrViewItem *it = view->getCurrentKrViewItem(); if (it->name() == "..") { newPath = KIO::upUrl(virtualPath()); } else { FileItem *v = func->getFileItem(it); // If it's a directory different from ".." if (v && v->isDir() && v->getName() != "..") { newPath = v->getUrl(); } else { // If it's a supported compressed file if (v && KRarcHandler::arcSupported(v->getMime())) { newPath = func->browsableArchivePath(v->getUrl().fileName()); } else { newPath = virtualPath(); } } } otherPanel()->func->openUrl(newPath); } else { func->openUrl(otherPanel()->virtualPath()); } return; } else e->ignore(); break; case Qt::Key_Down : if (e->modifiers() == Qt::ControlModifier) { // give the keyboard focus to the command line if (MAIN_VIEW->cmdLine()->isVisible()) MAIN_VIEW->cmdLineFocus(); else MAIN_VIEW->focusTerminalEmulator(); return; } else if (e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { // give the keyboard focus to TE MAIN_VIEW->focusTerminalEmulator(); } else e->ignore(); break; case Qt::Key_Up : if (e->modifiers() == Qt::ControlModifier) { // give the keyboard focus to the url navigator editLocation(); return; } else e->ignore(); break; case Qt::Key_Escape: cancelProgress(); break; default: // if we got this, it means that the view is not doing // the quick search thing, so send the characters to the commandline, if normal key if (e->modifiers() == Qt::NoModifier) MAIN_VIEW->cmdLine()->addText(e->text()); //e->ignore(); } } void ListPanel::showEvent(QShowEvent *e) { panelVisible(); QWidget::showEvent(e); } void ListPanel::hideEvent(QHideEvent *e) { panelHidden(); QWidget::hideEvent(e); } void ListPanel::panelVisible() { func->setPaused(false); } void ListPanel::panelHidden() { func->setPaused(true); } void ListPanel::slotPreviewJobStarted(KJob *job) { previewJob = job; connect(job, SIGNAL(percent(KJob*,ulong)), SLOT(slotPreviewJobPercent(KJob*,ulong))); connect(job, &KJob::result, this, &ListPanel::slotPreviewJobResult); cancelProgressButton->setMaximumHeight(sidebarButton->height()); cancelProgressButton->show(); previewProgress->setValue(0); previewProgress->setFormat(i18n("loading previews: %p%")); previewProgress->setMaximumHeight(cancelProgressButton->height()); previewProgress->show(); } void ListPanel::slotPreviewJobPercent(KJob* /*job*/, unsigned long percent) { previewProgress->setValue(percent); } void ListPanel::slotPreviewJobResult(KJob* /*job*/) { previewJob = nullptr; previewProgress->hide(); if(!inlineRefreshJob) cancelProgressButton->hide(); } void ListPanel::slotRefreshJobStarted(KIO::Job* job) { // disable the parts of the panel we don't want touched status->setEnabled(false); urlNavigator->setEnabled(false); cdRootButton->setEnabled(false); cdHomeButton->setEnabled(false); cdUpButton->setEnabled(false); cdOtherButton->setEnabled(false); sidebarButton->setEnabled(false); if(sidebar) sidebar->setEnabled(false); bookmarksButton->setEnabled(false); historyButton->setEnabled(false); syncBrowseButton->setEnabled(false); // connect to the job interface to provide in-panel refresh notification connect(job, &KIO::Job::infoMessage, this, &ListPanel::inlineRefreshInfoMessage); connect(job, SIGNAL(percent(KJob*,ulong)), SLOT(inlineRefreshPercent(KJob*,ulong))); connect(job, &KIO::Job::result, this, &ListPanel::inlineRefreshListResult); inlineRefreshJob = job; totals->setText(i18n(">> Reading...")); cancelProgressButton->show(); } void ListPanel::cancelProgress() { if (inlineRefreshJob) { disconnect(inlineRefreshJob, nullptr, this, nullptr); inlineRefreshJob->kill(KJob::EmitResult); inlineRefreshListResult(nullptr); } if(previewJob) { disconnect(previewJob, nullptr, this, nullptr); previewJob->kill(KJob::EmitResult); slotPreviewJobResult(nullptr); } } void ListPanel::setNavigatorUrl(const QUrl &url) { _navigatorUrl = url; urlNavigator->setLocationUrl(url); } void ListPanel::inlineRefreshPercent(KJob*, unsigned long perc) { QString msg = i18n(">> Reading: %1 % complete...", perc); totals->setText(msg); } void ListPanel::inlineRefreshInfoMessage(KJob*, const QString &msg) { totals->setText(i18n(">> Reading: %1", msg)); } void ListPanel::inlineRefreshListResult(KJob*) { if(inlineRefreshJob) disconnect(inlineRefreshJob, nullptr, this, nullptr); inlineRefreshJob = nullptr; // reenable everything status->setEnabled(true); urlNavigator->setEnabled(true); cdRootButton->setEnabled(true); cdHomeButton->setEnabled(true); cdUpButton->setEnabled(true); cdOtherButton->setEnabled(true); sidebarButton->setEnabled(true); if(sidebar) sidebar->setEnabled(true); bookmarksButton->setEnabled(true); historyButton->setEnabled(true); syncBrowseButton->setEnabled(true); if(!previewJob) cancelProgressButton->hide(); } void ListPanel::jumpBack() { func->openUrl(_jumpBackURL); } void ListPanel::setJumpBack(QUrl url) { _jumpBackURL = std::move(url); } void ListPanel::slotFilesystemError(const QString& msg) { slotRefreshColors(); fileSystemError->setText(i18n("Error: %1", msg)); fileSystemError->show(); } void ListPanel::showButtonMenu(QToolButton *b) { if(this != ACTIVE_PANEL) slotFocusOnMe(); if(b->isHidden()) b->menu()->exec(mapToGlobal(clientArea->pos())); else b->click(); } void ListPanel::openBookmarks() { showButtonMenu(bookmarksButton); } void ListPanel::openHistory() { showButtonMenu(historyButton); } void ListPanel::openMedia() { showButtonMenu(mediaButton); } void ListPanel::rightclickMenu() { if (view->getCurrentKrViewItem()) popRightClickMenu(mapToGlobal(view->getCurrentKrViewItem()->itemRect().topLeft())); } void ListPanel::toggleSyncBrowse() { syncBrowseButton->toggle(); } void ListPanel::editLocation() { urlNavigator->setUrlEditable(true); urlNavigator->setFocus(); urlNavigator->editor()->lineEdit()->selectAll(); } void ListPanel::showSearchBar() { searchBar->showBar(KrSearchBar::MODE_SEARCH); } void ListPanel::showSearchBarSelection() { searchBar->showBar(KrSearchBar::MODE_SELECT); } void ListPanel::showSearchBarFilter() { searchBar->showBar(KrSearchBar::MODE_FILTER); } void ListPanel::saveSettings(KConfigGroup cfg, bool saveHistory) { QUrl url = virtualPath(); url.setPassword(QString()); // make sure no password is saved cfg.writeEntry("Url", url.toString()); cfg.writeEntry("Type", getType()); cfg.writeEntry("Properties", getProperties()); cfg.writeEntry("PinnedUrl", pinnedUrl().toString()); if(saveHistory) func->history->save(KConfigGroup(&cfg, "History")); view->saveSettings(KConfigGroup(&cfg, "View")); // splitter/sidebar state if (sidebar && !sidebar->isHidden()) { sidebar->saveSettings(KConfigGroup(&cfg, "PanelPopup")); cfg.writeEntry("PopupPosition", sidebarPosition()); cfg.writeEntry("SplitterSizes", sidebarSplitter->saveState()); cfg.writeEntry("PopupPage", sidebar->currentPage()); } else { cfg.deleteEntry("PopupPosition"); cfg.deleteEntry("SplitterSizes"); cfg.deleteEntry("PopupPage"); } } void ListPanel::restoreSettings(KConfigGroup cfg) { changeType(cfg.readEntry("Type", defaultPanelType())); view->restoreSettings(KConfigGroup(&cfg, "View")); // "locked" property must be set after URL path is restored! // This panel can be reused when loading a profile, // so we reset its properties before calling openUrl(). setProperties(0); _lastLocalPath = ROOT_DIR; if(func->history->restore(KConfigGroup(&cfg, "History"))) { func->refresh(); } else { QUrl url(cfg.readEntry("Url", "invalid")); if (!url.isValid()) url = QUrl::fromLocalFile(ROOT_DIR); func->openUrl(url); } setJumpBack(func->history->currentUrl()); setProperties(cfg.readEntry("Properties", 0)); if (isPinned()) { QUrl pinnedUrl(cfg.readEntry("PinnedUrl", "invalid")); if (!pinnedUrl.isValid()) { pinnedUrl = func->history->currentUrl(); } func->openUrl(pinnedUrl); setPinnedUrl(pinnedUrl); } if (cfg.hasKey("PopupPosition")) { // sidebar was visible, restore toggleSidebar(); // create and show sidebar->restoreSettings(KConfigGroup(&cfg, "PanelPopup")); setSidebarPosition(cfg.readEntry("PopupPosition", 42 /* dummy */)); sidebarSplitter->restoreState(cfg.readEntry("SplitterSizes", QByteArray())); sidebar->setCurrentPage(cfg.readEntry("PopupPage", 0)); } } void ListPanel::slotCurrentChanged(KrViewItem *item) { // update status bar if (item) krApp->statusBarUpdate(item->description()); // update sidebar; which panel to display on? Sidebar *p; if (sidebar && !sidebar->isHidden()) { p = sidebar; } else if(otherPanel()->gui->sidebar && !otherPanel()->gui->sidebar->isHidden()) { p = otherPanel()->gui->sidebar; } else { return; } p->update(item ? func->files()->getFileItem(item->name()) : nullptr); } void ListPanel::otherPanelChanged() { func->syncURL = QUrl(); } void ListPanel::getFocusCandidates(QVector &widgets) { if(urlNavigator->editor()->isVisible()) widgets << urlNavigator->editor(); if(view->widget()->isVisible()) widgets << view->widget(); if(sidebar && sidebar->isVisible()) widgets << sidebar; } void ListPanel::updateButtons() { backButton->setEnabled(func->history->canGoBack()); forwardButton->setEnabled(func->history->canGoForward()); historyButton->setEnabled(func->history->count() > 1); cdRootButton->setEnabled(!virtualPath().matches(QUrl::fromLocalFile(ROOT_DIR), QUrl::StripTrailingSlash)); cdUpButton->setEnabled(!func->files()->isRoot()); cdHomeButton->setEnabled(!func->atHome()); } void ListPanel::newTab(KrViewItem *it) { if (!it) return; else if (it->name() == "..") { newTab(KIO::upUrl(virtualPath()), true); } else if (func->getFileItem(it)->isDir()) { QUrl url = virtualPath(); url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (it->name())); newTab(url, true); } } void ListPanel::newTab(const QUrl &url, bool nextToThis) { _manager->newTab(url, nextToThis ? this : nullptr); } void ListPanel::slotNavigatorUrlChanged(const QUrl &url) { if (url == _navigatorUrl) return; // this is the URL we just set ourself if (!isNavigatorEditModeSet()) { urlNavigator->setUrlEditable(false); } func->openUrl(KrServices::escapeFileUrl(url), QString(), true); } void ListPanel::resetNavigatorMode() { if (isNavigatorEditModeSet()) return; // set to "navigate" mode if url wasn't changed if (urlNavigator->uncommittedUrl().matches(virtualPath(), QUrl::StripTrailingSlash)) { // NOTE: this also sets focus to the navigator urlNavigator->setUrlEditable(false); slotFocusOnMe(); } } int ListPanel::sidebarPosition() const { int pos = sidebarSplitter->orientation() == Qt::Vertical ? 1 : 0; return pos + (qobject_cast(sidebarSplitter->widget(0)) == NULL ? 2 : 0); } void ListPanel::setSidebarPosition(int pos) { sidebarSplitter->setOrientation(pos % 2 == 0 ? Qt::Horizontal : Qt::Vertical); if ((pos < 2) != (qobject_cast(sidebarSplitter->widget(0)) != NULL)) { sidebarSplitter->insertWidget(0, sidebarSplitter->widget(1)); // swapping widgets in splitter } } void ListPanel::connectQuickSizeCalculator(SizeCalculator *sizeCalculator) { connect(sizeCalculator, &SizeCalculator::started, this, [=]() { quickSizeCalcProgress->reset(); quickSizeCalcProgress->show(); cancelQuickSizeCalcButton->show(); }); connect(cancelQuickSizeCalcButton, &QToolButton::clicked, sizeCalculator, &SizeCalculator::cancel); connect(sizeCalculator, &SizeCalculator::progressChanged, quickSizeCalcProgress, &QProgressBar::setValue); connect(sizeCalculator, &SizeCalculator::finished, this, [=]() { cancelQuickSizeCalcButton->hide(); quickSizeCalcProgress->hide(); }); } diff --git a/krusader/Panel/listpanel.h b/krusader/Panel/listpanel.h index f19d60e2..9c0fb064 100644 --- a/krusader/Panel/listpanel.h +++ b/krusader/Panel/listpanel.h @@ -1,258 +1,258 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 LISTPANEL_H #define LISTPANEL_H // QtCore #include #include #include #include #include #include // QtGui #include #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include "krpanel.h" #define PROP_SYNC_BUTTON_ON 1 #define PROP_LOCKED 2 #define PROP_PINNED 4 class DirHistoryButton; class KrBookmarkButton; class KrErrorDisplay; class KrSqueezedTextLabel; class KrSearchBar; class KrView; class KrViewItem; class ListPanelActions; class ListPanelFunc; class MediaButton; class Sidebar; class SizeCalculator; class ListPanel : public QWidget, public KrPanel { friend class ListPanelFunc; Q_OBJECT public: enum TabState { DEFAULT, LOCKED, // locked tab with changeable address PINNED }; // constructor create the panel, but DOESN'T fill it with data, use start() ListPanel(QWidget *parent, AbstractPanelManager *manager, const KConfigGroup& cfg = KConfigGroup()); ~ListPanel() override; - void otherPanelChanged() Q_DECL_OVERRIDE; + void otherPanelChanged() override; void start(const QUrl &url = QUrl()); void reparent(QWidget *parent, AbstractPanelManager *manager); int getType() { return panelType; } void changeType(int); bool isLocked() { return _tabState == TabState::LOCKED; } bool isPinned() { return _tabState == TabState::PINNED; } void setTabState(TabState tabState) { _tabState = tabState; } ListPanelActions *actions() { return _actions; } QString lastLocalPath() const; QString getCurrentName() const; QStringList getSelectedNames(); void setButtons(); void setJumpBack(QUrl url); int getProperties(); void setProperties(int); void getFocusCandidates(QVector &widgets); void saveSettings(KConfigGroup cfg, bool saveHistory); void restoreSettings(KConfigGroup cfg); void setPinnedUrl(QUrl &pinnedUrl) { _pinnedUrl = pinnedUrl; }; QUrl pinnedUrl() const { return _pinnedUrl; }; public slots: void handleDrop(QDropEvent *event, bool onView = false); // handle drops on frame or view void handleDrop(const QUrl &destination, QDropEvent *event); // handle drops with destination void popRightClickMenu(const QPoint&); void popEmptyRightClickMenu(const QPoint &); void compareDirs(bool otherPanelToo = true); void slotFocusOnMe(bool focus = true); void slotUpdateTotals(); // react to file changes in filesystem (path change or refresh) void slotStartUpdate(bool directoryChange); void toggleSidebar(); void panelVisible(); // called when the panel becomes active void panelHidden(); // called when panel becomes inactive void slotRefreshColors(); void cancelProgress(); // cancel filesystem refresh and/or preview (if running) void setNavigatorUrl(const QUrl &url); void openMedia(); void openHistory(); void openBookmarks(); void rightclickMenu(); void toggleSyncBrowse(); void editLocation(); void showSearchBar(); void showSearchBarSelection(); void showSearchBarFilter(); void jumpBack(); void setJumpBack() { setJumpBack(virtualPath()); } ///////////////////////// service functions - called internally //////////////////////// void prepareToDelete(); // internal use only protected: - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent*) Q_DECL_OVERRIDE { + void keyPressEvent(QKeyEvent *e) override; + void mousePressEvent(QMouseEvent*) override { slotFocusOnMe(); } - void showEvent(QShowEvent *) Q_DECL_OVERRIDE; - void hideEvent(QHideEvent *) Q_DECL_OVERRIDE; - bool eventFilter(QObject * watched, QEvent * e) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *) override; + void hideEvent(QHideEvent *) override; + bool eventFilter(QObject * watched, QEvent * e) override; void showButtonMenu(QToolButton *b); void createView(); void updateButtons(); static int defaultPanelType(); static bool isNavigatorEditModeSet(); // return the navigator edit mode setting protected slots: void slotCurrentChanged(KrViewItem *item); void startDragging(const QStringList&, const QPixmap&); void slotPreviewJobStarted(KJob *job); void slotPreviewJobPercent(KJob *job, unsigned long percent); void slotPreviewJobResult(KJob *job); // those handle the in-panel refresh notifications void slotRefreshJobStarted(KIO::Job* job); void inlineRefreshInfoMessage(KJob* job, const QString &msg); void inlineRefreshListResult(KJob* job); void inlineRefreshPercent(KJob*, unsigned long); void slotFilesystemError(const QString& msg); void newTab(KrViewItem *item); void newTab(const QUrl &url, bool nextToThis = false); void slotNavigatorUrlChanged(const QUrl &url); void resetNavigatorMode(); // set navigator mode after focus was lost // update filesystem meta info, disk-free and mount status void updateFilesystemStats(const QString &metaInfo, const QString &fsType, KIO::filesize_t total, KIO::filesize_t free); signals: void signalStatus(QString msg); // emitted when we need to update the status bar void pathChanged(const QUrl &url); // directory changed or refreshed void activate(); // emitted when the user changes panels void finishedDragging(); // NOTE: currently not used void signalRefreshColors(bool active); protected: int panelType; QString _lastLocalPath; QUrl _jumpBackURL; int colorMask; bool compareMode; //FilterSpec filter; KJob *previewJob; KIO::Job *inlineRefreshJob; ListPanelActions *_actions; QPixmap currDragPix; QWidget *clientArea; QSplitter *sidebarSplitter; KUrlNavigator* urlNavigator; KrSearchBar* searchBar; QToolButton *backButton, *forwardButton; QToolButton *cdRootButton; QToolButton *cdHomeButton; QToolButton *cdUpButton; QToolButton *cdOtherButton; QToolButton *sidebarPositionButton; QToolButton *sidebarButton; Sidebar *sidebar; // lazy initialized KrBookmarkButton *bookmarksButton; KrSqueezedTextLabel *status, *totals, *freeSpace; QProgressBar *quickSizeCalcProgress; QToolButton *cancelQuickSizeCalcButton; QProgressBar *previewProgress; DirHistoryButton* historyButton; MediaButton *mediaButton; QToolButton *syncBrowseButton; QToolButton *cancelProgressButton; // for thumbnail previews and filesystem refresh KrErrorDisplay *fileSystemError; private: bool handleDropInternal(QDropEvent *event, const QString &dir); int sidebarPosition() const; // 0: West, 1: North, 2: East, 3: South void setSidebarPosition(int); void connectQuickSizeCalculator(SizeCalculator *sizeCalculator); private: QUrl _navigatorUrl; // distinguish between new user set URL and new custom set URL QUrl _pinnedUrl; // only for TabState::PINNED TabState _tabState; QList sidebarSplitterSizes; }; #endif diff --git a/krusader/Panel/listpanelframe.h b/krusader/Panel/listpanelframe.h index edd6e4e4..2c9aa284 100644 --- a/krusader/Panel/listpanelframe.h +++ b/krusader/Panel/listpanelframe.h @@ -1,60 +1,60 @@ /***************************************************************************** * Copyright (C) 2010 Jan Lepper * * Copyright (C) 2010-2019 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 LISTPANELFRAME_H #define LISTPANELFRAME_H // QtGui #include // QtWidgets #include # include class QDragEnterEvent; class ListPanelFrame : public QFrame { Q_OBJECT public: ListPanelFrame(QWidget *parent, const QString& color); signals: void dropped(QDropEvent*, QWidget*); /**< emitted when someone drops URL onto the frame */ protected slots: void colorsChanged(); public slots: void refreshColors(bool active); protected: QColor getColor(KConfigGroup &cg, const QString& name, const QColor &def, const QColor &kdedef); - void dropEvent(QDropEvent *e) Q_DECL_OVERRIDE { + void dropEvent(QDropEvent *e) override { emit dropped(e, this); } - void dragEnterEvent(QDragEnterEvent*) Q_DECL_OVERRIDE; + void dragEnterEvent(QDragEnterEvent*) override; QString color; QPalette palActive, palInactive; }; #endif // LISTPANELFRAME_H diff --git a/krusader/Panel/sidebar.h b/krusader/Panel/sidebar.h index 78360390..5b04dc8c 100644 --- a/krusader/Panel/sidebar.h +++ b/krusader/Panel/sidebar.h @@ -1,102 +1,102 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * Copyright (C) 2004-2019 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 SIDEBAR_H #define SIDEBAR_H // QtCore #include // QtWidgets #include #include #include #include #include #include #include class KrSqueezedTextLabel; class PanelViewer; class DiskUsageViewer; class KrFileTreeView; class FileItem; /** * Additional side widget showing various meta information for the current file/directories. */ class Sidebar: public QWidget { Q_OBJECT enum Parts { /** Folder tree view */ Tree, /** Preview image for current file/directory */ Preview, /** File view: show file in most appropriate, read-only editor */ View, /** Disk usage for current directory structure */ DskUsage, /** Dummy */ Last = 0xFF }; public: explicit Sidebar(QWidget *parent); ~Sidebar() override; inline int currentPage() const { return stack->currentWidget()->property("KrusaderWidgetId").toInt(); } void saveSettings(const KConfigGroup& cfg) const; void restoreSettings(const KConfigGroup &cfg); void setCurrentPage(int); public slots: void update(const FileItem *fileitem); void onPanelPathChange(const QUrl &url); void show(); void hide(); signals: void urlActivated(const QUrl &url); void hideMe(); protected slots: void tabSelected(int id); void handleOpenUrlRequest(const QUrl &url); protected: - void focusInEvent(QFocusEvent*) Q_DECL_OVERRIDE; + void focusInEvent(QFocusEvent*) override; bool _hidden; QStackedWidget *stack; KImageFilePreview *imageFilePreview; KrSqueezedTextLabel *dataLine; QPointer pjob; KrFileTreeView *tree; QToolButton *treeBtn, *previewBtn, *viewerBtn, *duBtn; QButtonGroup *btns; PanelViewer *fileViewer; DiskUsageViewer *diskusage; }; #endif diff --git a/krusader/Search/krsearchdialog.cpp b/krusader/Search/krsearchdialog.cpp index e5795ff0..f21fd41c 100644 --- a/krusader/Search/krsearchdialog.cpp +++ b/krusader/Search/krsearchdialog.cpp @@ -1,674 +1,674 @@ /***************************************************************************** * Copyright (C) 2001 Shie Erlich * * Copyright (C) 2001 Rafi Yanai * * Copyright (C) 2004-2019 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 "krsearchdialog.h" // QtCore #include #include // QtGui #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include "krsearchmod.h" #include "../Dialogs/krdialogs.h" #include "../Dialogs/krspecialwidgets.h" #include "../Dialogs/krsqueezedtextlabel.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/krquery.h" #include "../FileSystem/virtualfilesystem.h" #include "../Filter/filtertabs.h" #include "../Filter/generalfilter.h" #include "../KViewer/krviewer.h" #include "../Panel/PanelView/krview.h" #include "../Panel/PanelView/krviewfactory.h" #include "../Panel/PanelView/krviewitem.h" #include "../Panel/krpanel.h" #include "../Panel/krsearchbar.h" #include "../Panel/panelfunc.h" #include "../defaults.h" #include "../kractions.h" #include "../krglobal.h" #include "../filelisticon.h" #include "../krservices.h" #include "../krslots.h" #include "../krusaderview.h" #include "../panelmanager.h" #define RESULTVIEW_TYPE 0 class SearchResultContainer : public DirListerInterface { public: explicit SearchResultContainer(QObject *parent) : DirListerInterface(parent) {} ~SearchResultContainer() override { clear(); } - QList fileItems() const Q_DECL_OVERRIDE { + QList fileItems() const override { return _fileItems; } - unsigned long numFileItems() const Q_DECL_OVERRIDE { + unsigned long numFileItems() const override { return _fileItems.count(); } - bool isRoot() const Q_DECL_OVERRIDE { + bool isRoot() const override { return true; } void clear() { emit cleared(); foreach(FileItem *fileitem, _fileItems) delete fileitem; _fileItems.clear(); _foundText.clear(); } void addItem(const FileItem &file, const QString &foundText) { const QString path = file.getUrl().toDisplayString(QUrl::PreferLocalFile); FileItem *fileitem = FileItem::createCopy(file, path); _fileItems << fileitem; if(!foundText.isEmpty()) _foundText[fileitem] = foundText; emit addedFileItem(fileitem); } QString foundText(const FileItem *fileitem) { return _foundText[fileitem]; } private: QList _fileItems; QHash _foundText; }; KrSearchDialog *KrSearchDialog::SearchDialog = nullptr; QString KrSearchDialog::lastSearchText = QString('*'); int KrSearchDialog::lastSearchType = 0; bool KrSearchDialog::lastSearchForCase = false; bool KrSearchDialog::lastContainsWholeWord = false; bool KrSearchDialog::lastContainsWithCase = false; bool KrSearchDialog::lastSearchInSubDirs = true; bool KrSearchDialog::lastSearchInArchives = false; bool KrSearchDialog::lastFollowSymLinks = false; bool KrSearchDialog::lastContainsRegExp = false; // class starts here ///////////////////////////////////////// KrSearchDialog::KrSearchDialog(const QString& profile, QWidget* parent) : QDialog(parent), query(nullptr), searcher(nullptr), isBusy(false), closed(false) { KConfigGroup group(krConfig, "Search"); setWindowTitle(i18n("Krusader::Search")); setWindowIcon(Icon("system-search")); auto* searchBaseLayout = new QGridLayout(this); searchBaseLayout->setSpacing(6); searchBaseLayout->setContentsMargins(11, 11, 11, 11); // creating the dialog buttons ( Search, Stop, Close ) auto* buttonsLayout = new QHBoxLayout(); buttonsLayout->setSpacing(6); buttonsLayout->setContentsMargins(0, 0, 0, 0); profileManager = new ProfileManager("SearcherProfile", this); buttonsLayout->addWidget(profileManager); searchTextToClipboard = new QCheckBox(this); searchTextToClipboard->setText(i18n("Query to clipboard")); searchTextToClipboard->setToolTip(i18n("Place search text to clipboard when a found file is opened.")); searchTextToClipboard->setCheckState(static_cast(group.readEntry("QueryToClipboard", 0))); connect(searchTextToClipboard, &QCheckBox::stateChanged, this, [=](int state) { KConfigGroup group(krConfig, "Search"); group.writeEntry("QueryToClipboard", state); }); buttonsLayout->addWidget(searchTextToClipboard); auto* spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); buttonsLayout->addItem(spacer); mainSearchBtn = new QPushButton(this); mainSearchBtn->setText(i18n("Search")); mainSearchBtn->setIcon(Icon("edit-find")); mainSearchBtn->setDefault(true); buttonsLayout->addWidget(mainSearchBtn); mainStopBtn = new QPushButton(this); mainStopBtn->setEnabled(false); mainStopBtn->setText(i18n("Stop")); mainStopBtn->setIcon(Icon("process-stop")); buttonsLayout->addWidget(mainStopBtn); mainCloseBtn = new QPushButton(this); mainCloseBtn->setText(i18n("Close")); mainCloseBtn->setIcon(Icon("dialog-close")); buttonsLayout->addWidget(mainCloseBtn); searchBaseLayout->addLayout(buttonsLayout, 1, 0); // creating the searcher tabs searcherTabs = new QTabWidget(this); filterTabs = FilterTabs::addTo(searcherTabs, FilterTabs::Default); generalFilter = dynamic_cast(filterTabs->get("GeneralFilter")); // creating the result tab QWidget* resultTab = new QWidget(searcherTabs); auto* resultLayout = new QGridLayout(resultTab); resultLayout->setSpacing(6); resultLayout->setContentsMargins(6, 6, 6, 6); // actions viewAction = new QAction(Icon("document-edit-preview"), i18n("View File"), this); viewAction->setShortcut(Qt::Key_F3); connect(viewAction, &QAction::triggered, this, &KrSearchDialog::viewCurrent); addAction(viewAction); editAction = new QAction(Icon("document-edit-sign"), i18n("Edit File"), this); editAction->setShortcut(Qt::Key_F4); connect(editAction, &QAction::triggered, this, &KrSearchDialog::editCurrent); addAction(editAction); compareAction = new QAction(i18n("Compare by content"), this); compareAction->setShortcut(Qt::Key_F10); connect(compareAction, &QAction::triggered, this, &KrSearchDialog::compareByContent); addAction(compareAction); copyAction = KStandardAction::create(KStandardAction::Copy, this, SLOT(copyToClipBoard()), this); copyAction->setText(i18n("Copy to Clipboard")); addAction(copyAction); connect(searcherTabs, &QTabWidget::currentChanged, this, [=](int index) { bool resultTabShown = index == searcherTabs->indexOf(resultTab); viewAction->setEnabled(resultTabShown); editAction->setEnabled(resultTabShown); compareAction->setEnabled(resultTabShown); copyAction->setEnabled(resultTabShown); }); // creating the result list view result = new SearchResultContainer(this); // the view resultView = KrViewFactory::createView(RESULTVIEW_TYPE, resultTab, krConfig); resultView->init(false); resultView->restoreSettings(KConfigGroup(&group, "ResultView")); resultView->setMainWindow(this); resultView->prepareForActive(); resultView->refreshColors(); resultView->setFiles(result); resultView->refresh(); resultLayout->addWidget(resultView->widget(), 0, 0); // search bar - hidden by default searchBar = new KrSearchBar(resultView, this); searchBar->hide(); resultLayout->addWidget(searchBar, 1, 0); // text found row foundTextFrame = new QFrame(resultTab); foundTextFrame->setFrameShape(QLabel::StyledPanel); foundTextFrame->setFrameShadow(QLabel::Sunken); auto* foundTextLayout = new QHBoxLayout(); foundTextLayout->setSpacing(6); QLabel *textFoundLabel = new QLabel(i18n("Text found:"), resultTab); foundTextLayout->addWidget(textFoundLabel); foundTextLabel = new KrSqueezedTextLabel(resultTab); foundTextLayout->addWidget(foundTextLabel); foundTextFrame->setLayout(foundTextLayout); foundTextFrame->hide(); resultLayout->addWidget(foundTextFrame, 2, 0); // result info row auto* resultLabelLayout = new QHBoxLayout(); resultLabelLayout->setSpacing(6); resultLabelLayout->setContentsMargins(0, 0, 0, 0); searchingLabel = new KSqueezedTextLabel(i18n("Idle"), resultTab); resultLabelLayout->addWidget(searchingLabel); foundLabel = new QLabel("", resultTab); resultLabelLayout->addWidget(foundLabel); mainFeedToListBoxBtn = new QPushButton(QIcon::fromTheme("list-add"), i18n("Feed to listbox"), this); mainFeedToListBoxBtn->setEnabled(false); resultLabelLayout->addWidget(mainFeedToListBoxBtn); resultLayout->addLayout(resultLabelLayout, 3, 0); searcherTabs->addTab(resultTab, i18n("&Results")); searchBaseLayout->addWidget(searcherTabs, 0, 0); // signals and slots connections connect(mainSearchBtn, &QPushButton::clicked, this, &KrSearchDialog::startSearch); connect(mainStopBtn, &QPushButton::clicked, this, &KrSearchDialog::stopSearch); connect(mainCloseBtn, &QPushButton::clicked, this, &KrSearchDialog::closeDialog); connect(mainFeedToListBoxBtn, &QPushButton::clicked, this, &KrSearchDialog::feedToListBox); connect(profileManager, &ProfileManager::loadFromProfile, filterTabs, &FilterTabs::loadFromProfile); connect(profileManager, &ProfileManager::saveToProfile, filterTabs, &FilterTabs::saveToProfile); connect(resultView->op(), &KrViewOperator::currentChanged, this, &KrSearchDialog::currentChanged); connect(resultView->op(), &KrViewOperator::executed, this, &KrSearchDialog::executed); connect(resultView->op(), &KrViewOperator::contextMenu, this, &KrSearchDialog::contextMenu); // tab order setTabOrder(mainSearchBtn, mainCloseBtn); setTabOrder(mainCloseBtn, mainStopBtn); setTabOrder(mainStopBtn, searcherTabs); setTabOrder(searcherTabs, resultView->widget()); sizeX = group.readEntry("Window Width", -1); sizeY = group.readEntry("Window Height", -1); if (sizeX != -1 && sizeY != -1) resize(sizeX, sizeY); if (group.readEntry("Window Maximized", false)) showMaximized(); else show(); generalFilter->searchFor->setFocus(); // finally, load a profile of apply defaults: if (profile.isEmpty()) { // load the last used values generalFilter->searchFor->setEditText(lastSearchText); generalFilter->searchFor->lineEdit()->selectAll(); generalFilter->ofType->setCurrentIndex(lastSearchType); generalFilter->searchForCase->setChecked(lastSearchForCase); generalFilter->containsWholeWord->setChecked(lastContainsWholeWord); generalFilter->containsTextCase->setChecked(lastContainsWithCase); generalFilter->containsRegExp->setChecked(lastContainsRegExp); generalFilter->searchInDirs->setChecked(lastSearchInSubDirs); generalFilter->searchInArchives->setChecked(lastSearchInArchives); generalFilter->followLinks->setChecked(lastFollowSymLinks); // the path in the active panel should be the default search location generalFilter->searchIn->lineEdit()->setText(ACTIVE_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)); } else profileManager->loadProfile(profile); // important: call this _after_ you've connected profileManager ot the loadFromProfile!! } KrSearchDialog::~KrSearchDialog() { delete query; query = nullptr; delete resultView; resultView = nullptr; } void KrSearchDialog::closeDialog(bool isAccept) { if(isBusy) { closed = true; return; } // stop the search if it's on-going if (searcher != nullptr) { delete searcher; searcher = nullptr; } // saving the searcher state KConfigGroup group(krConfig, "Search"); group.writeEntry("Window Width", sizeX); group.writeEntry("Window Height", sizeY); group.writeEntry("Window Maximized", isMaximized()); resultView->saveSettings(KConfigGroup(&group, "ResultView")); lastSearchText = generalFilter->searchFor->currentText(); lastSearchType = generalFilter->ofType->currentIndex(); lastSearchForCase = generalFilter->searchForCase->isChecked(); lastContainsWholeWord = generalFilter->containsWholeWord->isChecked(); lastContainsWithCase = generalFilter->containsTextCase->isChecked(); lastContainsRegExp = generalFilter->containsRegExp->isChecked(); lastSearchInSubDirs = generalFilter->searchInDirs->isChecked(); lastSearchInArchives = generalFilter->searchInArchives->isChecked(); lastFollowSymLinks = generalFilter->followLinks->isChecked(); hide(); SearchDialog = nullptr; if (isAccept) QDialog::accept(); else QDialog::reject(); this->deleteLater(); } void KrSearchDialog::reject() { closeDialog(false); } void KrSearchDialog::resizeEvent(QResizeEvent *e) { if (!isMaximized()) { sizeX = e->size().width(); sizeY = e->size().height(); } } void KrSearchDialog::slotFound(const FileItem &file, const QString &foundText) { result->addItem(file, foundText); foundLabel->setText(i18np("Found %1 match.", "Found %1 matches.", result->numFileItems())); } bool KrSearchDialog::gui2query() { // prepare the query ... /////////////////// names, locations and greps if (query != nullptr) { delete query; query = nullptr; } query = new KRQuery(); return filterTabs->fillQuery(query); } void KrSearchDialog::startSearch() { if(isBusy) return; // prepare the query ///////////////////////////////////////////// if (!gui2query()) return; // first, informative messages if (query->searchInArchives()) { KMessageBox::information(this, i18n("Since you chose to also search in archives, " "note the following limitations:\n" "You cannot search for text (grep) while doing" " a search that includes archives."), nullptr, "searchInArchives"); } // prepare the gui /////////////////////////////////////////////// result->clear(); resultView->setSortMode(KrViewProperties::NoColumn, 0); foundTextFrame->setVisible(!query->content().isEmpty()); foundTextLabel->setText(""); searchingLabel->setText(""); foundLabel->setText(i18n("Found 0 matches.")); mainFeedToListBoxBtn->setEnabled(false); mainSearchBtn->setEnabled(false); mainStopBtn->setEnabled(true); mainCloseBtn->setEnabled(false); searcherTabs->setCurrentIndex(2); // show the results page isBusy = true; qApp->processEvents(); // start the search. if (searcher != nullptr) abort(); searcher = new KRSearchMod(query); connect(searcher, &KRSearchMod::searching, searchingLabel, &KSqueezedTextLabel::setText); connect(searcher, &KRSearchMod::found, this, &KrSearchDialog::slotFound); connect(searcher, &KRSearchMod::finished, this, &KrSearchDialog::stopSearch); searcher->start(); isBusy = false; delete searcher; searcher = nullptr; // gui stuff mainSearchBtn->setEnabled(true); mainCloseBtn->setEnabled(true); mainStopBtn->setEnabled(false); if (result->numFileItems()) mainFeedToListBoxBtn->setEnabled(true); searchingLabel->setText(i18n("Finished searching.")); // go to the first result. Note: `getFirst()` doesn't cause problems // if the results list is empty resultView->setCurrentKrViewItem(resultView->getFirst()); if (closed) closeDialog(); } void KrSearchDialog::stopSearch() { if (searcher != nullptr) { searcher->stop(); disconnect(searcher, nullptr, nullptr, nullptr); } } void KrSearchDialog::executed(const QString &name) { // 'name' is (local) file path or complete URL QString path = name; QString fileName; if(!name.endsWith('/')) { // not a directory, split filename and path int idx = name.lastIndexOf("/"); fileName = name.mid(idx+1); path = name.left(idx); } QUrl url(path); if (url.scheme().isEmpty()) { url = QUrl::fromLocalFile(path); } ACTIVE_FUNC->openUrl(url, fileName); showMinimized(); } void KrSearchDialog::currentChanged(KrViewItem *item) { if(!item) return; QString text = result->foundText(item->getFileItem()); if(!text.isEmpty()) { // ugly hack: find the and in the text, then // use it to set the are which we don't want squeezed int idx = text.indexOf("") - 4; // take "" into account int length = text.indexOf("") - idx + 4; foundTextLabel->setText(text, idx, length); } } void KrSearchDialog::closeEvent(QCloseEvent *e) { /* if searching is in progress we must not close the window */ if (isBusy) /* because qApp->processEvents() is called by the searcher and */ { /* at window destruction, the searcher object will be deleted */ stopSearch(); /* instead we stop searching */ closed = true; /* and after stopping: startSearch can close the window */ e->ignore(); /* ignoring the close event */ } else QDialog::closeEvent(e); /* if no searching, let QDialog handle the event */ } void KrSearchDialog::keyPressEvent(QKeyEvent *e) { // TODO: don't use hardcoded shortcuts if (isBusy && e->key() == Qt::Key_Escape) { /* at searching we must not close the window */ stopSearch(); /* so we simply stop searching */ return; } if (resultView->widget()->hasFocus()) { if ((e->key() | e->modifiers()) == (Qt::CTRL | Qt::Key_I)) { searchBar->showBar(KrSearchBar::MODE_FILTER); } } QDialog::keyPressEvent(e); } void KrSearchDialog::editCurrent() { tryPlaceSearchQueryToClipboard(); KrViewItem *current = resultView->getCurrentKrViewItem(); if (current) KrViewer::edit(current->getFileItem()->getUrl(), this); } void KrSearchDialog::viewCurrent() { tryPlaceSearchQueryToClipboard(); KrViewItem *current = resultView->getCurrentKrViewItem(); if (current) KrViewer::view(current->getFileItem()->getUrl(), this); } void KrSearchDialog::compareByContent() { const KrViewItemList list = resultView->getSelectedKrViewItems(); if (list.count() != 2) return; SLOTS->compareContent(list[0]->getFileItem()->getUrl(),list[1]->getFileItem()->getUrl()); } void KrSearchDialog::contextMenu(const QPoint &pos) { // create the menu QMenu popup; popup.setTitle(i18n("Krusader Search")); popup.addAction(viewAction); popup.addAction(editAction); popup.addAction(compareAction); compareAction->setEnabled(resultView->numSelected() == 2); popup.addSeparator(); popup.addAction(copyAction); popup.exec(pos); } void KrSearchDialog::feedToListBox() { VirtualFileSystem virtFilesystem; virtFilesystem.scanDir(QUrl::fromLocalFile("/")); KConfigGroup group(krConfig, "Search"); int listBoxNum = group.readEntry("Feed To Listbox Counter", 1); QString queryName; if(query) { const QString where = KrServices::toStringList(query->searchInDirs()).join(", "); queryName = query->content().isEmpty() ? i18n("Search results for \"%1\" in %2", query->nameFilter(), where) : i18n("Search results for \"%1\" containing \"%2\" in %3", query->nameFilter(), query->content(), where); } QString fileSystemName; do { fileSystemName = i18n("Search results") + QString(" %1").arg(listBoxNum++); } while (virtFilesystem.getFileItem(fileSystemName) != nullptr); group.writeEntry("Feed To Listbox Counter", listBoxNum); KConfigGroup ga(krConfig, "Advanced"); if (ga.readEntry("Confirm Feed to Listbox", _ConfirmFeedToListbox)) { bool ok; fileSystemName = QInputDialog::getText(this, i18n("Query name"), i18n("Here you can name the file collection"), QLineEdit::Normal, fileSystemName, &ok); if (! ok) return; } QList urlList; foreach(FileItem *fileitem, result->fileItems()) urlList.push_back(fileitem->getUrl()); mainSearchBtn->setEnabled(false); mainCloseBtn->setEnabled(false); mainFeedToListBoxBtn->setEnabled(false); isBusy = true; const QUrl url = QUrl(QString("virt:/") + fileSystemName); virtFilesystem.scanDir(url); virtFilesystem.addFiles(urlList); virtFilesystem.setMetaInformation(queryName); //ACTIVE_FUNC->openUrl(url); ACTIVE_MNG->slotNewTab(url); isBusy = false; closeDialog(); } void KrSearchDialog::copyToClipBoard() { const KrViewItemList selectedItems = resultView->getSelectedKrViewItems(); QList urls; for (KrViewItem *item : selectedItems) { urls.append(item->getFileItem()->getUrl()); } if (urls.count() == 0) return; auto *mimeData = new QMimeData; mimeData->setImageData(FileListIcon("file").pixmap()); mimeData->setUrls(urls); QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); } void KrSearchDialog::tryPlaceSearchQueryToClipboard() { if (searchTextToClipboard->isChecked() && !generalFilter->containsText->currentText().isEmpty() && QApplication::clipboard()->text() != generalFilter->containsText->currentText()) { QApplication::clipboard()->setText(generalFilter->containsText->currentText()); } } diff --git a/krusader/Search/krsearchdialog.h b/krusader/Search/krsearchdialog.h index d449fad0..2ca1ee0b 100644 --- a/krusader/Search/krsearchdialog.h +++ b/krusader/Search/krsearchdialog.h @@ -1,137 +1,137 @@ /***************************************************************************** * Copyright (C) 2001 Shie Erlich * * Copyright (C) 2001 Rafi Yanai * * Copyright (C) 2004-2019 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 KRSEARCHDIALOG_H #define KRSEARCHDIALOG_H // QtCore #include #include // QtWidgets #include #include #include #include class FileItem; class FilterTabs; class GeneralFilter; class KrSearchBar; class KrSqueezedTextLabel; class KrView; class KrViewItem; class KRQuery; class KRSearchMod; class KSqueezedTextLabel; class ProfileManager; class SearchResultContainer; class KrSearchDialog : public QDialog { Q_OBJECT public: explicit KrSearchDialog(const QString& profile = QString(), QWidget* parent = nullptr); ~KrSearchDialog() override; void prepareGUI(); static KrSearchDialog *SearchDialog; public slots: void startSearch(); void stopSearch(); void feedToListBox(); void slotFound(const FileItem &file, const QString &foundText); void closeDialog(bool isAccept = true); void executed(const QString &name); void currentChanged(KrViewItem *item); void contextMenu(const QPoint &); - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; - void closeEvent(QCloseEvent *e) Q_DECL_OVERRIDE; - void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) override; + void closeEvent(QCloseEvent *e) override; + void resizeEvent(QResizeEvent *e) override; protected slots: - void reject() Q_DECL_OVERRIDE; + void reject() override; private slots: void editCurrent(); void viewCurrent(); void compareByContent(); void copyToClipBoard(); private: bool gui2query(); /** * Placing search query to clipboard is optional (opt-in). * So user has clipboard untact by default when opening found documents, * but can enable it persistently by checking "Query to clipboard" checkbox. */ void tryPlaceSearchQueryToClipboard(); private: ProfileManager *profileManager; QCheckBox *searchTextToClipboard; FilterTabs * filterTabs; GeneralFilter * generalFilter; QPushButton* mainSearchBtn; QPushButton* mainStopBtn; QPushButton* mainCloseBtn; QPushButton* mainFeedToListBoxBtn; QTabWidget* searcherTabs; QLabel* foundLabel; KrSqueezedTextLabel *foundTextLabel; KSqueezedTextLabel *searchingLabel; SearchResultContainer *result; KrView *resultView; KrSearchBar *searchBar; QFrame *foundTextFrame; KRQuery *query; KRSearchMod *searcher; bool isBusy; bool closed; QAction *viewAction; QAction *editAction; QAction *compareAction; QAction *copyAction; static QString lastSearchText; static int lastSearchType; static bool lastSearchForCase; static bool lastContainsWholeWord; static bool lastContainsWithCase; static bool lastSearchInSubDirs; static bool lastSearchInArchives; static bool lastFollowSymLinks; static bool lastContainsRegExp; int sizeX; int sizeY; }; #endif diff --git a/krusader/Splitter/splittergui.h b/krusader/Splitter/splittergui.h index 17f419fa..d649c358 100644 --- a/krusader/Splitter/splittergui.h +++ b/krusader/Splitter/splittergui.h @@ -1,74 +1,74 @@ /***************************************************************************** * Copyright (C) 2003 Csaba Karai * * Copyright (C) 2004-2019 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 SPLITTERGUI_H #define SPLITTERGUI_H // QtCore #include // QtWidgets #include #include #include class QComboBox; class QCheckBox; class QDoubleSpinBox; class SplitterGUI : public QDialog { Q_OBJECT private: struct PredefinedDevice; static const QList &predefinedDevices(); KIO::filesize_t userDefinedSize; int lastSelectedDevice; KIO::filesize_t division; QDoubleSpinBox *spinBox; QComboBox *deviceCombo; QComboBox *sizeCombo; QCheckBox *overwriteCb; KUrlRequester *urlReq; public: SplitterGUI(QWidget* parent, const QUrl& fileURL, const QUrl& defaultDir); ~SplitterGUI() override; QUrl getDestinationDir() { return urlReq->url(); } KIO::filesize_t getSplitSize(); bool overWriteFiles(); public slots: virtual void sizeComboActivated(int item); virtual void predefinedComboActivated(int item); virtual void splitPressed(); protected: - void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) override; }; #endif /* __SPLITTERGUI_H__ */ diff --git a/krusader/Synchronizer/synchronizergui.cpp b/krusader/Synchronizer/synchronizergui.cpp index 2c708317..f3b8f43a 100644 --- a/krusader/Synchronizer/synchronizergui.cpp +++ b/krusader/Synchronizer/synchronizergui.cpp @@ -1,1586 +1,1586 @@ /***************************************************************************** * Copyright (C) 2003 Csaba Karai * * Copyright (C) 2004-2019 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 "synchronizergui.h" #include "../krglobal.h" #include "../filelisticon.h" #include "../defaults.h" #include "../krusaderview.h" #include "../Panel/listpanel.h" #include "../Panel/panelfunc.h" #include "../FileSystem/krpermhandler.h" #include "../KViewer/krviewer.h" #include "../Dialogs/krspwidgets.h" #include "../FileSystem/krquery.h" #include "../krservices.h" #include "../krslots.h" #include "synchronizedialog.h" #include "feedtolistboxdialog.h" #include "synchronizercolors.h" // QtCore #include #include #include #include // QtGui #include #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class SynchronizerListView : public KrTreeWidget { private: Synchronizer *synchronizer; bool isLeft; public: SynchronizerListView(Synchronizer * sync, QWidget * parent) : KrTreeWidget(parent), synchronizer(sync) { } - void mouseMoveEvent(QMouseEvent * e) Q_DECL_OVERRIDE { + void mouseMoveEvent(QMouseEvent * e) override { isLeft = ((e->modifiers() & Qt::ShiftModifier) == 0); KrTreeWidget::mouseMoveEvent(e); } - void startDrag(Qt::DropActions /* supportedActs */) Q_DECL_OVERRIDE { + void startDrag(Qt::DropActions /* supportedActs */) override { QList urls; unsigned ndx = 0; SynchronizerFileItem *currentItem; while ((currentItem = synchronizer->getItemAt(ndx++)) != nullptr) { auto *viewItem = (SynchronizerGUI::SyncViewItem *)currentItem->userData(); if (!viewItem || !viewItem->isSelected() || viewItem->isHidden()) continue; SynchronizerFileItem *item = viewItem->synchronizerItemRef(); if (item) { if (isLeft && item->existsInLeft()) { QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; QUrl leftURL = Synchronizer::fsUrl(synchronizer->leftBaseDirectory() + leftDirName + item->leftName()); urls.push_back(leftURL); } else if (!isLeft && item->existsInRight()) { QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; QUrl rightURL = Synchronizer::fsUrl(synchronizer->rightBaseDirectory() + rightDirName + item->rightName()); urls.push_back(rightURL); } } } if (urls.count() == 0) return; auto *drag = new QDrag(this); auto *mimeData = new QMimeData; mimeData->setImageData(FileListIcon(isLeft ? "arrow-left-double" : "arrow-right-double").pixmap()); mimeData->setUrls(urls); drag->setMimeData(mimeData); drag->exec(); } }; SynchronizerGUI::SynchronizerGUI(QWidget* parent, QUrl leftURL, QUrl rightURL, QStringList selList) : QDialog(parent) { initGUI(QString(), std::move(leftURL), std::move(rightURL), std::move(selList)); } SynchronizerGUI::SynchronizerGUI(QWidget* parent, QString profile) : QDialog(parent) { initGUI(std::move(profile), QUrl(), QUrl(), QStringList()); } void SynchronizerGUI::initGUI(const QString& profileName, QUrl leftURL, QUrl rightURL, QStringList selList) { setAttribute(Qt::WA_DeleteOnClose); selectedFiles = std::move(selList); isComparing = wasClosed = wasSync = false; hasSelectedFiles = (selectedFiles.count() != 0); if (leftURL.isEmpty()) leftURL = QUrl::fromLocalFile(ROOT_DIR); if (rightURL.isEmpty()) rightURL = QUrl::fromLocalFile(ROOT_DIR); setWindowTitle(i18n("Krusader::Synchronize Folders")); auto *synchGrid = new QGridLayout(this); synchGrid->setSpacing(6); synchGrid->setContentsMargins(11, 11, 11, 11); synchronizerTabs = new QTabWidget(this); /* ============================== Compare groupbox ============================== */ QWidget *synchronizerTab = new QWidget(this); auto *synchronizerGrid = new QGridLayout(synchronizerTab); synchronizerGrid->setSpacing(6); synchronizerGrid->setContentsMargins(11, 11, 11, 11); auto *compareDirs = new QGroupBox(synchronizerTab); compareDirs->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); compareDirs->setTitle(i18n("Folder Comparison")); auto *grid = new QGridLayout(compareDirs); grid->setSpacing(6); grid->setContentsMargins(11, 11, 11, 11); leftDirLabel = new QLabel(compareDirs); leftDirLabel->setAlignment(Qt::AlignHCenter); grid->addWidget(leftDirLabel, 0 , 0); QLabel *filterLabel = new QLabel(compareDirs); filterLabel->setText(i18n("File &Filter:")); filterLabel->setAlignment(Qt::AlignHCenter); grid->addWidget(filterLabel, 0 , 1); rightDirLabel = new QLabel(compareDirs); rightDirLabel->setAlignment(Qt::AlignHCenter); grid->addWidget(rightDirLabel, 0 , 2); KConfigGroup group(krConfig, "Synchronize"); leftLocation = new KHistoryComboBox(false, compareDirs); leftLocation->setMaxCount(25); // remember 25 items leftLocation->setDuplicatesEnabled(false); leftLocation->setEditable(true); leftLocation->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); QStringList list = group.readEntry("Left Folder History", QStringList()); leftLocation->setHistoryItems(list); auto *leftUrlReq = new KUrlRequester(leftLocation, compareDirs); leftUrlReq->setUrl(leftURL); leftUrlReq->setMode(KFile::Directory); leftUrlReq->setMinimumWidth(250); grid->addWidget(leftUrlReq, 1 , 0); leftLocation->setWhatsThis(i18n("The left base folder used during the synchronization process.")); leftUrlReq->setEnabled(!hasSelectedFiles); leftLocation->setEnabled(!hasSelectedFiles); leftDirLabel->setBuddy(leftLocation); fileFilter = new KHistoryComboBox(false, compareDirs); fileFilter->setMaxCount(25); // remember 25 items fileFilter->setDuplicatesEnabled(false); fileFilter->setMinimumWidth(100); fileFilter->setMaximumWidth(100); fileFilter->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); list = group.readEntry("File Filter", QStringList()); fileFilter->setHistoryItems(list); fileFilter->setEditText("*"); grid->addWidget(fileFilter, 1 , 1); filterLabel->setBuddy(fileFilter); QString wtFilter = "

" + 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*'.

"); fileFilter->setWhatsThis(wtFilter); filterLabel->setWhatsThis(wtFilter); rightLocation = new KHistoryComboBox(compareDirs); rightLocation->setMaxCount(25); // remember 25 items rightLocation->setDuplicatesEnabled(false); rightLocation->setEditable(true); rightLocation->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); list = group.readEntry("Right Folder History", QStringList()); rightLocation->setHistoryItems(list); auto *rightUrlReq = new KUrlRequester(rightLocation, compareDirs); rightUrlReq->setUrl(rightURL); rightUrlReq->setMode(KFile::Directory); rightUrlReq->setMinimumWidth(250); grid->addWidget(rightUrlReq, 1 , 2); rightLocation->setWhatsThis(i18n("The right base folder used during the synchronization process.")); rightUrlReq->setEnabled(!hasSelectedFiles); rightLocation->setEnabled(!hasSelectedFiles); rightDirLabel->setBuddy(rightLocation); QWidget *optionWidget = new QWidget(compareDirs); auto *optionBox = new QHBoxLayout(optionWidget); optionBox->setContentsMargins(0, 0, 0, 0); QWidget *optionGridWidget = new QWidget(optionWidget); auto *optionGrid = new QGridLayout(optionGridWidget); optionBox->addWidget(optionGridWidget); cbSubdirs = new QCheckBox(i18n("Recurse subfolders"), optionGridWidget); cbSubdirs->setChecked(group.readEntry("Recurse Subdirectories", _RecurseSubdirs)); optionGrid->addWidget(cbSubdirs, 0, 0); cbSubdirs->setWhatsThis(i18n("Compare not only the base folders but their subfolders as well.")); cbSymlinks = new QCheckBox(i18n("Follow symlinks"), optionGridWidget); cbSymlinks->setChecked(group.readEntry("Follow Symlinks", _FollowSymlinks)); cbSymlinks->setEnabled(cbSubdirs->isChecked()); optionGrid->addWidget(cbSymlinks, 0, 1); cbSymlinks->setWhatsThis(i18n("Follow symbolic links during the compare process.")); cbByContent = new QCheckBox(i18n("Compare by content"), optionGridWidget); cbByContent->setChecked(group.readEntry("Compare By Content", _CompareByContent)); optionGrid->addWidget(cbByContent, 0, 2); cbByContent->setWhatsThis(i18n("Compare duplicated files with same size by content.")); cbIgnoreDate = new QCheckBox(i18n("Ignore Date"), optionGridWidget); cbIgnoreDate->setChecked(group.readEntry("Ignore Date", _IgnoreDate)); optionGrid->addWidget(cbIgnoreDate, 1, 0); cbIgnoreDate->setWhatsThis(i18n("

Ignore date information during the compare process.

Note: useful if the files are located on network filesystems or in archives.

")); cbAsymmetric = new QCheckBox(i18n("Asymmetric"), optionGridWidget); cbAsymmetric->setChecked(group.readEntry("Asymmetric", _Asymmetric)); optionGrid->addWidget(cbAsymmetric, 1, 1); cbAsymmetric->setWhatsThis(i18n("

Asymmetric mode

The left side is the destination, the right is the source folder. Files existing only in the left folder will be deleted, the other differing ones will be copied from right to left.

Note: useful when updating a folder from a file server.

")); cbIgnoreCase = new QCheckBox(i18n("Ignore Case"), optionGridWidget); cbIgnoreCase->setChecked(group.readEntry("Ignore Case", _IgnoreCase)); optionGrid->addWidget(cbIgnoreCase, 1, 2); cbIgnoreCase->setWhatsThis(i18n("

Case insensitive filename compare.

Note: useful when synchronizing Windows filesystems.

")); /* =========================== Show options groupbox ============================= */ auto *showOptions = new QGroupBox(optionWidget); optionBox->addWidget(showOptions); showOptions->setTitle(i18n("S&how options")); showOptions->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); auto *showOptionsLayout = new QGridLayout(showOptions); showOptionsLayout->setSpacing(4); showOptionsLayout->setContentsMargins(11, 11, 11, 11); bool checked; QString description; checked = group.readEntry("LeftToRight Button", _BtnLeftToRight); description = i18n("Show files marked to Copy from left to right."); btnLeftToRight = createButton(showOptions, "arrow-right", checked, Qt::CTRL + Qt::Key_L, description, ">"); showOptionsLayout->addWidget(btnLeftToRight, 0, 0); checked = group.readEntry("Equals Button", _BtnEquals); description = i18n("Show files considered to be identical."); btnEquals = createButton(showOptions, "equals", checked, Qt::CTRL + Qt::Key_E, description, "="); showOptionsLayout->addWidget(btnEquals, 0, 1); checked = group.readEntry("Differents Button", _BtnDifferents); description = i18n("Show excluded files."); btnDifferents = createButton(showOptions, "unequals", checked, Qt::CTRL + Qt::Key_D, description, "!="); showOptionsLayout->addWidget(btnDifferents, 0, 2); checked = group.readEntry("RightToLeft Button", _BtnRightToLeft); description = i18n("Show files marked to Copy from right to left."); btnRightToLeft = createButton(showOptions, "arrow-left", checked, Qt::CTRL + Qt::Key_R, description, "<"); showOptionsLayout->addWidget(btnRightToLeft, 0, 3); checked = group.readEntry("Deletable Button", _BtnDeletable); description = i18n("Show files marked to delete."); btnDeletable = createButton(showOptions, "user-trash", checked, Qt::CTRL + Qt::Key_T, description); showOptionsLayout->addWidget(btnDeletable, 0, 4); checked = group.readEntry("Duplicates Button", _BtnDuplicates); description = i18n("Show files that exist on both sides."); btnDuplicates = createButton(showOptions, "arrow-up", checked, Qt::CTRL + Qt::Key_I, description, i18n("Duplicates"), true); showOptionsLayout->addWidget(btnDuplicates, 0, 5); checked = group.readEntry("Singles Button", _BtnSingles); description = i18n("Show files that exist on one side only."); btnSingles = createButton(showOptions, "arrow-down", checked, Qt::CTRL + Qt::Key_N, description, i18n("Singles"), true); showOptionsLayout->addWidget(btnSingles, 0, 6); grid->addWidget(optionWidget, 2, 0, 1, 3); synchronizerGrid->addWidget(compareDirs, 0, 0); /* ========================= Synchronization list view ========================== */ syncList = new SynchronizerListView(&synchronizer, synchronizerTab); // create the main container syncList->setWhatsThis(i18n("The compare results of the synchronizer (Ctrl+M).")); syncList->setAutoFillBackground(true); syncList->installEventFilter(this); KConfigGroup gl(krConfig, "Look&Feel"); syncList->setFont(gl.readEntry("Filelist Font", _FilelistFont)); syncList->setBackgroundRole(QPalette::Window); syncList->setAutoFillBackground(true); QStringList labels; labels << i18nc("@title:column file name", "Name"); // 0 labels << i18nc("@title:column", "Size"); // 1 labels << i18nc("@title:column", "Date"); // 2 labels << i18n("<=>"); // 3 labels << i18nc("@title:column", "Date"); // 4 labels << i18nc("@title:column", "Size"); // 5 labels << i18nc("@title:column file name", "Name"); // 6 syncList->setHeaderLabels(labels); QHeaderView *header = syncList->header(); if (group.hasKey("State")) { header->restoreState(group.readEntry("State", QByteArray())); } header->setSectionResizeMode(0, QHeaderView::Stretch); header->setSectionResizeMode(1, QHeaderView::ResizeToContents); header->setSectionResizeMode(2, QHeaderView::ResizeToContents); header->setSectionResizeMode(3, QHeaderView::ResizeToContents); header->setSectionResizeMode(4, QHeaderView::ResizeToContents); header->setSectionResizeMode(5, QHeaderView::ResizeToContents); header->setSectionResizeMode(6, QHeaderView::Stretch); header->setStretchLastSection(false); syncList->setAllColumnsShowFocus(true); syncList->setSelectionMode(QAbstractItemView::ExtendedSelection); syncList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); syncList->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); header->setSortIndicatorShown(false); syncList->setSortingEnabled(false); syncList->setRootIsDecorated(true); syncList->setIndentation(10); syncList->setDragEnabled(true); syncList->setAutoFillBackground(true); synchronizerGrid->addWidget(syncList, 1, 0); synchronizerTabs->addTab(synchronizerTab, i18n("&Synchronizer")); synchGrid->addWidget(synchronizerTabs, 0, 0); filterTabs = FilterTabs::addTo(synchronizerTabs, FilterTabs::HasDontSearchIn); generalFilter = dynamic_cast(filterTabs->get("GeneralFilter")); generalFilter->searchFor->setEditText(fileFilter->currentText()); generalFilter->searchForCase->setChecked(true); // creating the time shift, equality threshold, hidden files options auto *optionsGroup = new QGroupBox(generalFilter); optionsGroup->setTitle(i18n("&Options")); auto *optionsLayout = new QGridLayout(optionsGroup); optionsLayout->setAlignment(Qt::AlignTop); optionsLayout->setSpacing(6); optionsLayout->setContentsMargins(11, 11, 11, 11); QLabel * parallelThreadsLabel = new QLabel(i18n("Parallel threads:"), optionsGroup); optionsLayout->addWidget(parallelThreadsLabel, 0, 0); parallelThreadsSpinBox = new QSpinBox(optionsGroup); parallelThreadsSpinBox->setMinimum(1); parallelThreadsSpinBox->setMaximum(15); int parThreads = group.readEntry("Parallel Threads", 1); parallelThreadsSpinBox->setValue(parThreads); optionsLayout->addWidget(parallelThreadsSpinBox, 0, 1); QLabel * equalityLabel = new QLabel(i18n("Equality threshold:"), optionsGroup); optionsLayout->addWidget(equalityLabel, 1, 0); equalitySpinBox = new QSpinBox(optionsGroup); equalitySpinBox->setMaximum(9999); optionsLayout->addWidget(equalitySpinBox, 1, 1); equalityUnitCombo = new QComboBox(optionsGroup); equalityUnitCombo->addItem(i18n("sec")); equalityUnitCombo->addItem(i18n("min")); equalityUnitCombo->addItem(i18n("hour")); equalityUnitCombo->addItem(i18n("day")); optionsLayout->addWidget(equalityUnitCombo, 1, 2); QLabel * timeShiftLabel = new QLabel(i18n("Time shift (right-left):"), optionsGroup); optionsLayout->addWidget(timeShiftLabel, 2, 0); timeShiftSpinBox = new QSpinBox(optionsGroup); timeShiftSpinBox->setMinimum(-9999); timeShiftSpinBox->setMaximum(9999); optionsLayout->addWidget(timeShiftSpinBox, 2, 1); timeShiftUnitCombo = new QComboBox(optionsGroup); timeShiftUnitCombo->addItem(i18n("sec")); timeShiftUnitCombo->addItem(i18n("min")); timeShiftUnitCombo->addItem(i18n("hour")); timeShiftUnitCombo->addItem(i18n("day")); optionsLayout->addWidget(timeShiftUnitCombo, 2, 2); QFrame *line = new QFrame(optionsGroup); line->setFrameStyle(QFrame::HLine | QFrame::Sunken); optionsLayout->addWidget(line, 3, 0, 1, 3); ignoreHiddenFilesCB = new QCheckBox(i18n("Ignore hidden files"), optionsGroup); optionsLayout->addWidget(ignoreHiddenFilesCB, 4, 0, 1, 3); generalFilter->middleLayout->addWidget(optionsGroup); /* ================================== Buttons =================================== */ auto *buttons = new QHBoxLayout; buttons->setSpacing(6); buttons->setContentsMargins(0, 0, 0, 0); profileManager = new ProfileManager("SynchronizerProfile", this); profileManager->setShortcut(Qt::CTRL + Qt::Key_P); profileManager->setWhatsThis(i18n("Profile manager (Ctrl+P).")); buttons->addWidget(profileManager); btnSwapSides = new QPushButton(this); btnSwapSides->setIcon(Icon("document-swap")); btnSwapSides->setShortcut(Qt::CTRL + Qt::Key_S); btnSwapSides->setWhatsThis(i18n("Swap sides (Ctrl+S).")); buttons->addWidget(btnSwapSides); statusLabel = new QLabel(this); buttons->addWidget(statusLabel); auto* spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); buttons->addItem(spacer); btnCompareDirs = new QPushButton(this); btnCompareDirs->setText(i18n("Compare")); btnCompareDirs->setIcon(Icon("kr_comparedirs")); btnCompareDirs->setDefault(true); buttons->addWidget(btnCompareDirs); btnScrollResults = new QPushButton(this); btnScrollResults->setCheckable(true); btnScrollResults->setChecked(group.readEntry("Scroll Results", _ScrollResults)); btnScrollResults->hide(); if (btnScrollResults->isChecked()) btnScrollResults->setText(i18n("Quiet")); else btnScrollResults->setText(i18n("Scroll Results")); buttons->addWidget(btnScrollResults); btnStopComparing = new QPushButton(this); btnStopComparing->setText(i18n("Stop")); btnStopComparing->setIcon(Icon("process-stop")); btnStopComparing->setEnabled(false); buttons->addWidget(btnStopComparing); btnFeedToListBox = new QPushButton(this); btnFeedToListBox->setText(i18n("Feed to listbox")); btnFeedToListBox->setIcon(Icon("list-add")); btnFeedToListBox->setEnabled(false); btnFeedToListBox->hide(); buttons->addWidget(btnFeedToListBox); btnSynchronize = new QPushButton(this); btnSynchronize->setText(i18n("Synchronize")); btnSynchronize->setIcon(Icon("folder-sync")); btnSynchronize->setEnabled(false); buttons->addWidget(btnSynchronize); auto *btnCloseSync = new QPushButton(this); btnCloseSync->setText(i18n("Close")); btnCloseSync->setIcon(Icon("dialog-close")); buttons->addWidget(btnCloseSync); synchGrid->addLayout(buttons, 1, 0); /* =============================== Connect table ================================ */ connect(syncList, &KrTreeWidget::itemRightClicked, this, &SynchronizerGUI::rightMouseClicked); connect(syncList, &KrTreeWidget::itemActivated, this, &SynchronizerGUI::doubleClicked); connect(profileManager, &ProfileManager::loadFromProfile, this, &SynchronizerGUI::loadFromProfile); connect(profileManager, &ProfileManager::saveToProfile, this, &SynchronizerGUI::saveToProfile); connect(btnSwapSides, &QPushButton::clicked, this, &SynchronizerGUI::swapSides); connect(btnCompareDirs, &QPushButton::clicked, this, &SynchronizerGUI::compare); connect(btnStopComparing, &QPushButton::clicked, this, &SynchronizerGUI::stop); connect(btnFeedToListBox, &QPushButton::clicked, this, &SynchronizerGUI::feedToListBox); connect(btnSynchronize, &QPushButton::clicked, this, &SynchronizerGUI::synchronize); connect(btnScrollResults, &QPushButton::toggled, this, &SynchronizerGUI::setScrolling); connect(btnCloseSync, &QPushButton::clicked, this, &SynchronizerGUI::closeDialog); connect(cbSubdirs, &QCheckBox::toggled, this, &SynchronizerGUI::subdirsChecked); connect(cbAsymmetric, &QCheckBox::toggled, this, &SynchronizerGUI::setPanelLabels); connect(&synchronizer, &Synchronizer::comparedFileData, this, &SynchronizerGUI::addFile); connect(&synchronizer, &Synchronizer::markChanged, this, &SynchronizerGUI::markChanged); connect(&synchronizer, &Synchronizer::statusInfo, this, &SynchronizerGUI::statusInfo); connect(btnLeftToRight, &QPushButton::toggled, this, &SynchronizerGUI::refresh); connect(btnEquals, &QPushButton::toggled, this, &SynchronizerGUI::refresh); connect(btnDifferents, &QPushButton::toggled, this, &SynchronizerGUI::refresh); connect(btnRightToLeft, &QPushButton::toggled, this, &SynchronizerGUI::refresh); connect(btnDeletable, &QPushButton::toggled, this, &SynchronizerGUI::refresh); connect(btnDuplicates, &QPushButton::toggled, this, &SynchronizerGUI::refresh); connect(btnSingles, &QPushButton::toggled, this, &SynchronizerGUI::refresh); connect(fileFilter, &KHistoryComboBox::currentTextChanged, this, &SynchronizerGUI::connectFilters); connect(generalFilter->searchFor, &KHistoryComboBox::currentTextChanged, this, &SynchronizerGUI::connectFilters); connect(generalFilter->searchFor, &KHistoryComboBox::currentTextChanged, this, &SynchronizerGUI::setCompletion); connect(generalFilter->dontSearchIn, &KURLListRequester::checkValidity, this, &SynchronizerGUI::checkExcludeURLValidity); connect(profileManager, &ProfileManager::loadFromProfile, filterTabs, &FilterTabs::loadFromProfile); connect(profileManager, &ProfileManager::saveToProfile, filterTabs, &FilterTabs::saveToProfile); setPanelLabels(); setCompletion(); /* =============================== Loading the colors ================================ */ KConfigGroup gc(krConfig, "Colors"); QString COLOR_NAMES[] = { "Equals", "Differs", "LeftCopy", "RightCopy", "Delete" }; QPalette defaultPalette = QGuiApplication::palette(); DECLARE_SYNCHRONIZER_BACKGROUND_DEFAULTS; DECLARE_SYNCHRONIZER_FOREGROUND_DEFAULTS; for (int clr = 0; clr != TT_MAX; clr ++) { QString colorName = clr > 4 ? "Equals" : COLOR_NAMES[ clr ]; QColor backgroundDefault = clr > 4 ? defaultPalette.color(QPalette::Active, QPalette::Base) : SYNCHRONIZER_BACKGROUND_DEFAULTS[ clr ]; QColor foregroundDefault = clr > 4 ? defaultPalette.color(QPalette::Active, QPalette::Text) : SYNCHRONIZER_FOREGROUND_DEFAULTS[ clr ]; QString foreEntry = QString("Synchronizer ") + colorName + QString(" Foreground"); QString bckgEntry = QString("Synchronizer ") + colorName + QString(" Background"); if (gc.readEntry(foreEntry, QString()) == "KDE default") foreGrounds[ clr ] = QColor(); else if (gc.readEntry(foreEntry, QString()).isEmpty()) // KDE4 workaround, default color doesn't work foreGrounds[ clr ] = foregroundDefault; else foreGrounds[ clr ] = gc.readEntry(foreEntry, foregroundDefault); if (gc.readEntry(bckgEntry, QString()) == "KDE default") backGrounds[ clr ] = QColor(); else if (gc.readEntry(foreEntry, QString()).isEmpty()) // KDE4 workaround, default color doesn't work backGrounds[ clr ] = backgroundDefault; else backGrounds[ clr ] = gc.readEntry(bckgEntry, backgroundDefault); } if (backGrounds[ TT_EQUALS ].isValid()) { QPalette pal = syncList->palette(); pal.setColor(QPalette::Base, backGrounds[ TT_EQUALS ]); syncList->setPalette(pal); } if (group.readEntry("Window Maximized", false)) { setWindowState(windowState() | Qt::WindowMaximized); } else { int sx = group.readEntry("Window Width", -1); int sy = group.readEntry("Window Height", -1); if (sx != -1 && sy != -1) { resize(sx, sy); } } if (!profileName.isNull()) profileManager->loadProfile(profileName); synchronizer.setParentWidget(this); } SynchronizerGUI::~SynchronizerGUI() { syncList->clear(); // for sanity: deletes the references to the synchronizer list } void SynchronizerGUI::setPanelLabels() { if (hasSelectedFiles && cbAsymmetric->isChecked()) { leftDirLabel->setText(i18n("Selected files from targ&et folder:")); rightDirLabel->setText(i18n("Selected files from sou&rce folder:")); } else if (hasSelectedFiles && !cbAsymmetric->isChecked()) { leftDirLabel->setText(i18n("Selected files from &left folder:")); rightDirLabel->setText(i18n("Selected files from &right folder:")); } else if (cbAsymmetric->isChecked()) { leftDirLabel->setText(i18n("Targ&et folder:")); rightDirLabel->setText(i18n("Sou&rce folder:")); } else { leftDirLabel->setText(i18n("&Left folder:")); rightDirLabel->setText(i18n("&Right folder:")); } } void SynchronizerGUI::setCompletion() { generalFilter->dontSearchIn->setCompletionDir(Synchronizer::fsUrl(rightLocation->currentText())); } void SynchronizerGUI::checkExcludeURLValidity(QString &text, QString &error) { QUrl url = Synchronizer::fsUrl(text); if (url.isRelative()) return; QString leftBase = leftLocation->currentText(); if (!leftBase.endsWith('/')) leftBase += '/'; QUrl leftBaseURL = Synchronizer::fsUrl(leftBase); if (leftBaseURL.isParentOf(url) && !url.isParentOf(leftBaseURL)) { text = QDir(leftBaseURL.path()).relativeFilePath(url.path()); return; } QString rightBase = rightLocation->currentText(); if (!rightBase.endsWith('/')) rightBase += '/'; QUrl rightBaseURL = Synchronizer::fsUrl(rightBase); if (rightBaseURL.isParentOf(url) && !url.isParentOf(rightBaseURL)) { text = QDir(rightBaseURL.path()).relativeFilePath(url.path()); return; } error = i18n("URL must be the descendant of either the left or the right base URL."); } void SynchronizerGUI::doubleClicked(QTreeWidgetItem *itemIn) { if (!itemIn) return; auto *syncItem = dynamic_cast(itemIn); SynchronizerFileItem *item = syncItem->synchronizerItemRef(); if (item && item->existsInLeft() && item->existsInRight() && !item->isDir()) { QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; QUrl leftURL = Synchronizer::fsUrl(synchronizer.leftBaseDirectory() + leftDirName + item->leftName()); QUrl rightURL = Synchronizer::fsUrl(synchronizer.rightBaseDirectory() + rightDirName + item->rightName()); SLOTS->compareContent(leftURL,rightURL); } else if (item && item->isDir()) { itemIn->setExpanded(!itemIn->isExpanded()); } } void SynchronizerGUI::rightMouseClicked(QTreeWidgetItem *itemIn, const QPoint &pos) { // these are the values that will exist in the menu #define EXCLUDE_ID 90 #define RESTORE_ID 91 #define COPY_TO_LEFT_ID 92 #define COPY_TO_RIGHT_ID 93 #define REVERSE_DIR_ID 94 #define DELETE_ID 95 #define VIEW_LEFT_FILE_ID 96 #define VIEW_RIGHT_FILE_ID 97 #define COMPARE_FILES_ID 98 #define SELECT_ITEMS_ID 99 #define DESELECT_ITEMS_ID 100 #define INVERT_SELECTION_ID 101 #define SYNCH_WITH_KGET_ID 102 #define COPY_CLPBD_LEFT_ID 103 #define COPY_CLPBD_RIGHT_ID 104 ////////////////////////////////////////////////////////// if (!itemIn) return; auto *syncItem = dynamic_cast(itemIn); if (syncItem == nullptr) return; SynchronizerFileItem *item = syncItem->synchronizerItemRef(); bool isDuplicate = item->existsInLeft() && item->existsInRight(); bool isDir = item->isDir(); // create the menu QMenu popup; QAction *myact; QHash< QAction *, int > actHash; popup.setTitle(i18n("Synchronize Folders")); myact = popup.addAction(i18n("E&xclude")); actHash[ myact ] = EXCLUDE_ID; myact = popup.addAction(i18n("Restore ori&ginal operation")); actHash[ myact ] = RESTORE_ID; myact = popup.addAction(i18n("Re&verse direction")); actHash[ myact ] = REVERSE_DIR_ID; myact = popup.addAction(i18n("Copy from &right to left")); actHash[ myact ] = COPY_TO_LEFT_ID; myact = popup.addAction(i18n("Copy from &left to right")); actHash[ myact ] = COPY_TO_RIGHT_ID; myact = popup.addAction(i18n("&Delete (left single)")); actHash[ myact ] = DELETE_ID; popup.addSeparator(); myact = popup.addAction(i18n("V&iew left file")); myact->setEnabled(!isDir && item->existsInLeft()); actHash[ myact ] = VIEW_LEFT_FILE_ID; myact = popup.addAction(i18n("Vi&ew right file")); myact->setEnabled(!isDir && item->existsInRight()); actHash[ myact ] = VIEW_RIGHT_FILE_ID; myact = popup.addAction(i18n("&Compare Files")); myact->setEnabled(!isDir && isDuplicate); actHash[ myact ] = COMPARE_FILES_ID; popup.addSeparator(); myact = popup.addAction(i18n("C&opy selected to clipboard (left)")); actHash[ myact ] = COPY_CLPBD_LEFT_ID; myact = popup.addAction(i18n("Co&py selected to clipboard (right)")); actHash[ myact ] = COPY_CLPBD_RIGHT_ID; popup.addSeparator(); myact = popup.addAction(i18n("&Select items")); actHash[ myact ] = SELECT_ITEMS_ID; myact = popup.addAction(i18n("Deselec&t items")); actHash[ myact ] = DESELECT_ITEMS_ID; myact = popup.addAction(i18n("I&nvert selection")); actHash[ myact ] = INVERT_SELECTION_ID; QUrl leftBDir = Synchronizer::fsUrl(synchronizer.leftBaseDirectory()); QUrl rightBDir = Synchronizer::fsUrl(synchronizer.rightBaseDirectory()); if (KrServices::cmdExist("kget") && ((!leftBDir.isLocalFile() && rightBDir.isLocalFile() && btnLeftToRight->isChecked()) || (leftBDir.isLocalFile() && !rightBDir.isLocalFile() && btnRightToLeft->isChecked()))) { popup.addSeparator(); myact = popup.addAction(i18n("Synchronize with &KGet")); actHash[ myact ] = SYNCH_WITH_KGET_ID; } QAction * res = popup.exec(pos); int result = -1; if (actHash.contains(res)) result = actHash[ res ]; if (result != -1) executeOperation(item, result); } void SynchronizerGUI::executeOperation(SynchronizerFileItem *item, int op) { // check out the user's option QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; QUrl leftURL = Synchronizer::fsUrl(synchronizer.leftBaseDirectory() + leftDirName + item->leftName()); QUrl rightURL = Synchronizer::fsUrl(synchronizer.rightBaseDirectory() + rightDirName + item->rightName()); switch (op) { case EXCLUDE_ID: case RESTORE_ID: case COPY_TO_LEFT_ID: case COPY_TO_RIGHT_ID: case REVERSE_DIR_ID: case DELETE_ID: { unsigned ndx = 0; SynchronizerFileItem *currentItem; while ((currentItem = synchronizer.getItemAt(ndx++)) != nullptr) { auto *viewItem = (SyncViewItem *)currentItem->userData(); if (!viewItem || !viewItem->isSelected() || viewItem->isHidden()) continue; switch (op) { case EXCLUDE_ID: synchronizer.exclude(viewItem->synchronizerItemRef()); break; case RESTORE_ID: synchronizer.restore(viewItem->synchronizerItemRef()); break; case REVERSE_DIR_ID: synchronizer.reverseDirection(viewItem->synchronizerItemRef()); break; case COPY_TO_LEFT_ID: synchronizer.copyToLeft(viewItem->synchronizerItemRef()); break; case COPY_TO_RIGHT_ID: synchronizer.copyToRight(viewItem->synchronizerItemRef()); break; case DELETE_ID: synchronizer.deleteLeft(viewItem->synchronizerItemRef()); break; } } refresh(); } break; case VIEW_LEFT_FILE_ID: KrViewer::view(leftURL, this); // view the file break; case VIEW_RIGHT_FILE_ID: KrViewer::view(rightURL, this); // view the file break; case COMPARE_FILES_ID: SLOTS->compareContent(leftURL,rightURL); break; case SELECT_ITEMS_ID: case DESELECT_ITEMS_ID: { KRQuery query = KRSpWidgets::getMask((op == SELECT_ITEMS_ID ? i18n("Select items") : i18n("Deselect items")), true, this); if (query.isNull()) break; unsigned ndx = 0; SynchronizerFileItem *currentItem; while ((currentItem = synchronizer.getItemAt(ndx++)) != nullptr) { auto *viewItem = (SyncViewItem *)currentItem->userData(); if (!viewItem || viewItem->isHidden()) continue; if (query.match(currentItem->leftName()) || query.match(currentItem->rightName())) viewItem->setSelected(op == SELECT_ITEMS_ID); } } break; case INVERT_SELECTION_ID: { unsigned ndx = 0; SynchronizerFileItem *currentItem; while ((currentItem = synchronizer.getItemAt(ndx++)) != nullptr) { auto *viewItem = (SyncViewItem *)currentItem->userData(); if (!viewItem || viewItem->isHidden()) continue; viewItem->setSelected(!viewItem->isSelected()); } } break; case SYNCH_WITH_KGET_ID: synchronizer.synchronizeWithKGet(); closeDialog(); break; case COPY_CLPBD_LEFT_ID: copyToClipboard(true); break; case COPY_CLPBD_RIGHT_ID: copyToClipboard(false); break; case -1 : return; // the user clicked outside of the menu } } void SynchronizerGUI::closeDialog() { if (isComparing) { stop(); wasClosed = true; return; } KConfigGroup group(krConfig, "Synchronize"); QStringList list; foreach(const QString &item, leftLocation->historyItems()) { QUrl url(item); // make sure no passwords are saved in config url.setPassword(QString()); list << url.toDisplayString(QUrl::PreferLocalFile); } group.writeEntry("Left Folder History", list); list.clear(); foreach(const QString &item, rightLocation->historyItems()) { QUrl url(item); // make sure no passwords are saved in config url.setPassword(QString()); list << url.toDisplayString(QUrl::PreferLocalFile); } group.writeEntry("Right Folder History", list); list = fileFilter->historyItems(); group.writeEntry("File Filter", list); group.writeEntry("Recurse Subdirectories", cbSubdirs->isChecked()); group.writeEntry("Follow Symlinks", cbSymlinks->isChecked()); group.writeEntry("Compare By Content", cbByContent->isChecked()); group.writeEntry("Ignore Date", cbIgnoreDate->isChecked()); group.writeEntry("Asymmetric", cbAsymmetric->isChecked()); group.writeEntry("Ignore Case", cbIgnoreCase->isChecked()); group.writeEntry("LeftToRight Button", btnLeftToRight->isChecked()); group.writeEntry("Equals Button", btnEquals->isChecked()); group.writeEntry("Differents Button", btnDifferents->isChecked()); group.writeEntry("RightToLeft Button", btnRightToLeft->isChecked()); group.writeEntry("Deletable Button", btnDeletable->isChecked()); group.writeEntry("Duplicates Button", btnDuplicates->isChecked()); group.writeEntry("Singles Button", btnSingles->isChecked()); group.writeEntry("Scroll Results", btnScrollResults->isChecked()); group.writeEntry("Parallel Threads", parallelThreadsSpinBox->value()); group.writeEntry("Window Width", size().width()); group.writeEntry("Window Height", size().height()); group.writeEntry("Window Maximized", isMaximized()); group.writeEntry("State", syncList->header()->saveState()); QDialog::reject(); this->deleteLater(); if (wasSync) { LEFT_PANEL->func->refresh(); RIGHT_PANEL->func->refresh(); ACTIVE_PANEL->gui->slotFocusOnMe(); } } void SynchronizerGUI::compare() { KRQuery query; if (!filterTabs->fillQuery(&query)) return; // perform some previous tests QString leftLocationTrimmed = leftLocation->currentText().trimmed(); QString rightLocationTrimmed = rightLocation->currentText().trimmed(); if (leftLocationTrimmed.isEmpty()) { KMessageBox::error(this, i18n("The target folder must not be empty.")); leftLocation->setFocus(); return; } if (rightLocationTrimmed.isEmpty()) { KMessageBox::error(this, i18n("The source folder must not be empty.")); rightLocation->setFocus(); return; } if (leftLocationTrimmed == rightLocationTrimmed) { if (KMessageBox::warningContinueCancel(this, i18n("Warning: The left and the right side are showing the same folder.")) != KMessageBox::Continue) { return; } } query.setNameFilter(fileFilter->currentText(), query.isCaseSensitive()); synchronizerTabs->setCurrentIndex(0); syncList->clear(); lastItem = nullptr; leftLocation->addToHistory(leftLocation->currentText()); rightLocation->addToHistory(rightLocation->currentText()); fileFilter->addToHistory(fileFilter->currentText()); setMarkFlags(); btnCompareDirs->setEnabled(false); profileManager->setEnabled(false); btnSwapSides->setEnabled(false); btnStopComparing->setEnabled(isComparing = true); btnStopComparing->show(); btnFeedToListBox->setEnabled(false); btnFeedToListBox->hide(); btnSynchronize->setEnabled(false); btnCompareDirs->hide(); btnScrollResults->show(); disableMarkButtons(); int fileCount = synchronizer.compare(leftLocation->currentText(), rightLocation->currentText(), &query, cbSubdirs->isChecked(), cbSymlinks->isChecked(), cbIgnoreDate->isChecked(), cbAsymmetric->isChecked(), cbByContent->isChecked(), cbIgnoreCase->isChecked(), btnScrollResults->isChecked(), selectedFiles, convertToSeconds(equalitySpinBox->value(), equalityUnitCombo->currentIndex()), convertToSeconds(timeShiftSpinBox->value(), timeShiftUnitCombo->currentIndex()), parallelThreadsSpinBox->value(), ignoreHiddenFilesCB->isChecked()); enableMarkButtons(); btnStopComparing->setEnabled(isComparing = false); btnStopComparing->hide(); btnFeedToListBox->show(); btnCompareDirs->setEnabled(true); profileManager->setEnabled(true); btnSwapSides->setEnabled(true); btnCompareDirs->show(); btnScrollResults->hide(); if (fileCount) { btnSynchronize->setEnabled(true); btnFeedToListBox->setEnabled(true); } syncList->setFocus(); if (wasClosed) closeDialog(); } void SynchronizerGUI::stop() { synchronizer.stop(); } void SynchronizerGUI::feedToListBox() { FeedToListBoxDialog listBox(this, &synchronizer, syncList, btnEquals->isChecked()); if (listBox.isAccepted()) closeDialog(); } void SynchronizerGUI::reject() { closeDialog(); } void SynchronizerGUI::addFile(SynchronizerFileItem *item) { QString leftName = "", rightName = "", leftDate = "", rightDate = "", leftSize = "", rightSize = ""; bool isDir = item->isDir(); QColor textColor = foreGrounds[ item->task()]; QColor baseColor = backGrounds[ item->task()]; if (item->existsInLeft()) { leftName = item->leftName(); leftSize = isDir ? dirLabel() + ' ' : KRpermHandler::parseSize(item->leftSize()); leftDate = SynchronizerGUI::convertTime(item->leftDate()); } if (item->existsInRight()) { rightName = item->rightName(); rightSize = isDir ? dirLabel() + ' ' : KRpermHandler::parseSize(item->rightSize()); rightDate = SynchronizerGUI::convertTime(item->rightDate()); } SyncViewItem *listItem = nullptr; SyncViewItem *dirItem; if (item->parent() == nullptr) { listItem = new SyncViewItem(item, textColor, baseColor, syncList, lastItem, leftName, leftSize, leftDate, Synchronizer::getTaskTypeName(item->task()), rightDate, rightSize, rightName); lastItem = listItem; } else { dirItem = (SyncViewItem *)item->parent()->userData(); if (dirItem) { dirItem->setExpanded(true); listItem = new SyncViewItem(item, textColor, baseColor, dirItem, dirItem->lastItem(), leftName, leftSize, leftDate, Synchronizer::getTaskTypeName(item->task()), rightDate, rightSize, rightName); dirItem->setLastItem(listItem); } } if (listItem) { listItem->setIcon(0, Icon(isDir ? "folder" : "document-new")); if (!item->isMarked()) listItem->setHidden(true); else syncList->scrollTo(syncList->indexOf(listItem)); } } void SynchronizerGUI::markChanged(SynchronizerFileItem *item, bool ensureVisible) { auto *listItem = (SyncViewItem *)item->userData(); if (listItem) { if (!item->isMarked()) { listItem->setHidden(true); } else { QString leftName = "", rightName = "", leftDate = "", rightDate = "", leftSize = "", rightSize = ""; bool isDir = item->isDir(); if (item->existsInLeft()) { leftName = item->leftName(); leftSize = isDir ? dirLabel() + ' ' : KRpermHandler::parseSize(item->leftSize()); leftDate = SynchronizerGUI::convertTime(item->leftDate()); } if (item->existsInRight()) { rightName = item->rightName(); rightSize = isDir ? dirLabel() + ' ' : KRpermHandler::parseSize(item->rightSize()); rightDate = SynchronizerGUI::convertTime(item->rightDate()); } listItem->setHidden(false); listItem->setText(0, leftName); listItem->setText(1, leftSize); listItem->setText(2, leftDate); listItem->setText(3, Synchronizer::getTaskTypeName(item->task())); listItem->setText(4, rightDate); listItem->setText(5, rightSize); listItem->setText(6, rightName); listItem->setColors(foreGrounds[ item->task()], backGrounds[ item->task()]); if (ensureVisible) syncList->scrollTo(syncList->indexOf(listItem)); } } } void SynchronizerGUI::subdirsChecked(bool isOn) { cbSymlinks->setEnabled(isOn); } void SynchronizerGUI::disableMarkButtons() { btnLeftToRight->setEnabled(false); btnEquals->setEnabled(false); btnDifferents->setEnabled(false); btnRightToLeft->setEnabled(false); btnDeletable->setEnabled(false); btnDuplicates->setEnabled(false); btnSingles->setEnabled(false); } void SynchronizerGUI::enableMarkButtons() { btnLeftToRight->setEnabled(true); btnEquals->setEnabled(true); btnDifferents->setEnabled(true); btnRightToLeft->setEnabled(true); btnDeletable->setEnabled(true); btnDuplicates->setEnabled(true); btnSingles->setEnabled(true); } QString SynchronizerGUI::convertTime(time_t time) const { // convert the time_t to struct tm struct tm* t = localtime((time_t *) & time); QDateTime tmp(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), QTime(t->tm_hour, t->tm_min)); return QLocale().toString(tmp, QLocale::ShortFormat); } void SynchronizerGUI::setMarkFlags() { synchronizer.setMarkFlags(btnRightToLeft->isChecked(), btnEquals->isChecked(), btnDifferents->isChecked(), btnLeftToRight->isChecked(), btnDuplicates->isChecked(), btnSingles->isChecked(), btnDeletable->isChecked()); } void SynchronizerGUI::refresh() { if (!isComparing) { syncList->clearSelection(); setMarkFlags(); btnCompareDirs->setEnabled(false); profileManager->setEnabled(false); btnSwapSides->setEnabled(false); btnSynchronize->setEnabled(false); btnFeedToListBox->setEnabled(false); disableMarkButtons(); int fileCount = synchronizer.refresh(); enableMarkButtons(); btnCompareDirs->setEnabled(true); profileManager->setEnabled(true); btnSwapSides->setEnabled(true); if (fileCount) { btnFeedToListBox->setEnabled(true); btnSynchronize->setEnabled(true); } } } void SynchronizerGUI::synchronize() { int copyToLeftNr, copyToRightNr, deleteNr; KIO::filesize_t copyToLeftSize, copyToRightSize, deleteSize; if (!synchronizer.totalSizes(©ToLeftNr, ©ToLeftSize, ©ToRightNr, ©ToRightSize, &deleteNr, &deleteSize)) { KMessageBox::sorry(parentWidget(), i18n("Synchronizer has nothing to do.")); return; } auto *sd = new SynchronizeDialog(this, &synchronizer, copyToLeftNr, copyToLeftSize, copyToRightNr, copyToRightSize, deleteNr, deleteSize, parallelThreadsSpinBox->value()); wasSync = sd->wasSyncronizationStarted(); delete sd; if (wasSync) closeDialog(); } void SynchronizerGUI::statusInfo(const QString& info) { statusLabel->setText(info); qApp->processEvents(); } void SynchronizerGUI::swapSides() { if (btnCompareDirs->isEnabled()) { QString leftCurrent = leftLocation->currentText(); leftLocation->lineEdit()->setText(rightLocation->currentText()); rightLocation->lineEdit()->setText(leftCurrent); synchronizer.swapSides(); refresh(); } } void SynchronizerGUI::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_M : { if (e->modifiers() == Qt::ControlModifier) { syncList->setFocus(); e->accept(); } break; } case Qt::Key_F3 : case Qt::Key_F4 : { e->accept(); syncList->setFocus(); QTreeWidgetItem *listItem = syncList->currentItem(); if (listItem == nullptr) break; bool isedit = e->key() == Qt::Key_F4; SynchronizerFileItem *item = (dynamic_cast(listItem))->synchronizerItemRef(); QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; if (item->isDir()) return; if (e->modifiers() == Qt::ShiftModifier && item->existsInRight()) { QUrl rightURL = Synchronizer::fsUrl(synchronizer.rightBaseDirectory() + rightDirName + item->rightName()); if (isedit) KrViewer::edit(rightURL, this); // view the file else KrViewer::view(rightURL, this); // view the file return; } else if (e->modifiers() == 0 && item->existsInLeft()) { QUrl leftURL = Synchronizer::fsUrl(synchronizer.leftBaseDirectory() + leftDirName + item->leftName()); if (isedit) KrViewer::edit(leftURL, this); // view the file else KrViewer::view(leftURL, this); // view the file return; } } break; case Qt::Key_U : if (e->modifiers() != Qt::ControlModifier) break; e->accept(); swapSides(); return; case Qt::Key_Escape: if (!btnStopComparing->isHidden() && btnStopComparing->isEnabled()) { // is it comparing? e->accept(); btnStopComparing->animateClick(); // just click the stop button } else { e->accept(); if (syncList->topLevelItemCount() != 0) { int result = KMessageBox::warningYesNo(this, i18n("The synchronizer window contains data from a previous compare. If you exit, this data will be lost. Do you really want to exit?"), i18n("Krusader::Synchronize Folders"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "syncGUIexit"); if (result != KMessageBox::Yes) return; } QDialog::reject(); } return; } QDialog::keyPressEvent(e); } bool SynchronizerGUI::eventFilter(QObject * /* watched */, QEvent * e) { if (e->type() == QEvent::KeyPress) { auto* ke = dynamic_cast( e); switch (ke->key()) { case Qt::Key_Down: case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Delete: case Qt::Key_W: { if (ke->key() == Qt::Key_W) { if (ke->modifiers() != Qt::ControlModifier) return false; } else if (ke->modifiers() != Qt::AltModifier) return false; int op = -1; switch (ke->key()) { case Qt::Key_Down: op = EXCLUDE_ID; break; case Qt::Key_Left: op = COPY_TO_LEFT_ID; break; case Qt::Key_Right: op = COPY_TO_RIGHT_ID; break; case Qt::Key_Up: op = RESTORE_ID; break; case Qt::Key_Delete: op = DELETE_ID; break; case Qt::Key_W: op = REVERSE_DIR_ID; break; } ke->accept(); QTreeWidgetItem *listItem = syncList->currentItem(); if (listItem == nullptr) return true; SynchronizerFileItem *item = (dynamic_cast(listItem))->synchronizerItemRef(); bool hasSelected = false; QList selected = syncList->selectedItems(); for (int i = 0; i != selected.count(); i++) if (selected[ i ]->isSelected() && !selected[ i ]->isHidden()) hasSelected = true; if (!hasSelected) listItem->setSelected(true); executeOperation(item, op); return true; } } } return false; } void SynchronizerGUI::loadFromProfile(const QString& profile) { syncList->clear(); synchronizer.reset(); isComparing = wasClosed = false; btnSynchronize->setEnabled(false); btnFeedToListBox->setEnabled(false); KConfigGroup pg(krConfig, profile); if (!hasSelectedFiles) { leftLocation->lineEdit()->setText(pg.readEntry("Left Location", QString())); rightLocation->lineEdit()->setText(pg.readEntry("Right Location", QString())); } fileFilter->lineEdit()->setText(pg.readEntry("Search For", QString())); cbSubdirs-> setChecked(pg.readEntry("Recurse Subdirectories", true)); cbSymlinks-> setChecked(pg.readEntry("Follow Symlinks", false)); cbByContent-> setChecked(pg.readEntry("Compare By Content", false)); cbIgnoreDate->setChecked(pg.readEntry("Ignore Date", false)); cbAsymmetric->setChecked(pg.readEntry("Asymmetric", false)); cbIgnoreCase->setChecked(pg.readEntry("Ignore Case", false)); btnScrollResults->setChecked(pg.readEntry("Scroll Results", false)); btnLeftToRight->setChecked(pg.readEntry("Show Left To Right", true)); btnEquals ->setChecked(pg.readEntry("Show Equals", true)); btnDifferents ->setChecked(pg.readEntry("Show Differents", true)); btnRightToLeft->setChecked(pg.readEntry("Show Right To Left", true)); btnDeletable ->setChecked(pg.readEntry("Show Deletable", true)); btnDuplicates ->setChecked(pg.readEntry("Show Duplicates", true)); btnSingles ->setChecked(pg.readEntry("Show Singles", true)); int equalityThreshold = pg.readEntry("Equality Threshold", 0); int equalityCombo = 0; convertFromSeconds(equalityThreshold, equalityCombo, equalityThreshold); equalitySpinBox->setValue(equalityThreshold); equalityUnitCombo->setCurrentIndex(equalityCombo); int timeShift = pg.readEntry("Time Shift", 0); int timeShiftCombo = 0; convertFromSeconds(timeShift, timeShiftCombo, timeShift); timeShiftSpinBox->setValue(timeShift); timeShiftUnitCombo->setCurrentIndex(timeShiftCombo); int parallelThreads = pg.readEntry("Parallel Threads", 1); parallelThreadsSpinBox->setValue(parallelThreads); bool ignoreHidden = pg.readEntry("Ignore Hidden Files", false); ignoreHiddenFilesCB->setChecked(ignoreHidden); refresh(); } void SynchronizerGUI::saveToProfile(const QString& profile) { KConfigGroup group(krConfig, profile); group.writeEntry("Left Location", leftLocation->currentText()); group.writeEntry("Search For", fileFilter->currentText()); group.writeEntry("Right Location", rightLocation->currentText()); group.writeEntry("Recurse Subdirectories", cbSubdirs->isChecked()); group.writeEntry("Follow Symlinks", cbSymlinks->isChecked()); group.writeEntry("Compare By Content", cbByContent->isChecked()); group.writeEntry("Ignore Date", cbIgnoreDate->isChecked()); group.writeEntry("Asymmetric", cbAsymmetric->isChecked()); group.writeEntry("Ignore Case", cbIgnoreCase->isChecked()); group.writeEntry("Scroll Results", btnScrollResults->isChecked()); group.writeEntry("Show Left To Right", btnLeftToRight->isChecked()); group.writeEntry("Show Equals", btnEquals->isChecked()); group.writeEntry("Show Differents", btnDifferents->isChecked()); group.writeEntry("Show Right To Left", btnRightToLeft->isChecked()); group.writeEntry("Show Deletable", btnDeletable->isChecked()); group.writeEntry("Show Duplicates", btnDuplicates->isChecked()); group.writeEntry("Show Singles", btnSingles->isChecked()); group.writeEntry("Equality Threshold", convertToSeconds(equalitySpinBox->value(), equalityUnitCombo->currentIndex())); group.writeEntry("Time Shift", convertToSeconds(timeShiftSpinBox->value(), timeShiftUnitCombo->currentIndex())); group.writeEntry("Parallel Threads", parallelThreadsSpinBox->value()); group.writeEntry("Ignore Hidden Files", ignoreHiddenFilesCB->isChecked()); } void SynchronizerGUI::connectFilters(const QString &newString) { if (synchronizerTabs->currentIndex()) fileFilter->setEditText(newString); else generalFilter->searchFor->setEditText(newString); } void SynchronizerGUI::setScrolling(bool isOn) { if (isOn) btnScrollResults->setText(i18n("Quiet")); else btnScrollResults->setText(i18n("Scroll Results")); synchronizer.setScrolling(isOn); } int SynchronizerGUI::convertToSeconds(int time, int unit) { switch (unit) { case 1: return time * 60; case 2: return time * 3600; case 3: return time * 86400; default: return time; } } void SynchronizerGUI::convertFromSeconds(int &time, int &unit, int second) { unit = 0; time = second; int absTime = (time < 0) ? -time : time; if (absTime >= 86400 && (absTime % 86400) == 0) { time /= 86400; unit = 3; } else if (absTime >= 3600 && (absTime % 3600) == 0) { time /= 3600; unit = 2; } else if (absTime >= 60 && (absTime % 60) == 0) { time /= 60; unit = 1; } } QPushButton *SynchronizerGUI::createButton(QWidget *parent, const QString &iconName, bool checked, const QKeySequence &shortCut, const QString &description, const QString &text, bool textAndIcon) { auto *button = new QPushButton(parent); bool iconExists = Icon::exists(iconName); if (!text.isEmpty() && (textAndIcon || !iconExists)) { button->setText(text); } if (iconExists) { button->setIcon(Icon(iconName)); } button->setCheckable(true); button->setChecked(checked); button->setShortcut(shortCut); const QString infoText = QString("%1 (%2)").arg(description, shortCut.toString(QKeySequence::NativeText)); button->setWhatsThis(infoText); button->setToolTip(infoText); return button; } void SynchronizerGUI::copyToClipboard(bool isLeft) { QList urls; unsigned ndx = 0; SynchronizerFileItem *currentItem; while ((currentItem = synchronizer.getItemAt(ndx++)) != nullptr) { auto *viewItem = (SynchronizerGUI::SyncViewItem *)currentItem->userData(); if (!viewItem || !viewItem->isSelected() || viewItem->isHidden()) continue; SynchronizerFileItem *item = viewItem->synchronizerItemRef(); if (item) { if (isLeft && item->existsInLeft()) { QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; QUrl leftURL = Synchronizer::fsUrl(synchronizer.leftBaseDirectory() + leftDirName + item->leftName()); urls.push_back(leftURL); } else if (!isLeft && item->existsInRight()) { QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; QUrl rightURL = Synchronizer::fsUrl(synchronizer.rightBaseDirectory() + rightDirName + item->rightName()); urls.push_back(rightURL); } } } if (urls.count() == 0) return; auto *mimeData = new QMimeData; mimeData->setImageData(FileListIcon(isLeft ? "arrow-left-double" : "arrow-right-double").pixmap()); mimeData->setUrls(urls); QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); } QString SynchronizerGUI::dirLabel() { //HACK add <> brackets AFTER translating - otherwise KUIT thinks it's a tag static QString label = QString("<") + i18nc("Show the string 'DIR' instead of file size in detailed view (for folders)", "DIR") + '>'; return label; } diff --git a/krusader/Synchronizer/synchronizergui.h b/krusader/Synchronizer/synchronizergui.h index 4d44a537..5513c72a 100644 --- a/krusader/Synchronizer/synchronizergui.h +++ b/krusader/Synchronizer/synchronizergui.h @@ -1,248 +1,248 @@ /***************************************************************************** * Copyright (C) 2003 Csaba Karai * * Copyright (C) 2004-2019 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 SYNCHRONIZERGUI_H #define SYNCHRONIZERGUI_H // QtCore #include // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include #include "synchronizer.h" #include "../GUI/profilemanager.h" #include "../GUI/krtreewidget.h" #include "../Filter/filtertabs.h" #include "../Filter/generalfilter.h" class QSpinBox; class SynchronizerGUI : public QDialog { Q_OBJECT public: class SyncViewItem : public QTreeWidgetItem { private: SynchronizerFileItem *syncItemRef; SyncViewItem *lastItemRef; public: SyncViewItem(SynchronizerFileItem *item, QColor txt, QColor base, QTreeWidget * parent, QTreeWidgetItem *after, const QString& label1, const QString& label2 = QString(), const QString& label3 = QString(), const QString& label4 = QString(), const QString& label5 = QString(), const QString& label6 = QString(), const QString& label7 = QString(), const QString& label8 = QString()) : QTreeWidgetItem(parent, after), syncItemRef(item), lastItemRef(nullptr) { setText(0, label1); setText(1, label2); setText(2, label3); setText(3, label4); setText(4, label5); setText(5, label6); setText(6, label7); setText(7, label8); setTextAlignment(1, Qt::AlignRight); setTextAlignment(3, Qt::AlignHCenter); setTextAlignment(5, Qt::AlignRight); item->setUserData((void *)this); setColors(std::move(txt), std::move(base)); } SyncViewItem(SynchronizerFileItem *item, QColor txt, QColor base, QTreeWidgetItem * parent, QTreeWidgetItem *after, const QString& label1, const QString& label2 = QString(), const QString& label3 = QString(), const QString& label4 = QString(), const QString& label5 = QString(), const QString& label6 = QString(), const QString& label7 = QString(), const QString& label8 = QString()) : QTreeWidgetItem(parent, after), syncItemRef(item), lastItemRef(nullptr) { setText(0, label1); setText(1, label2); setText(2, label3); setText(3, label4); setText(4, label5); setText(5, label6); setText(6, label7); setText(7, label8); setTextAlignment(1, Qt::AlignRight); setTextAlignment(3, Qt::AlignHCenter); setTextAlignment(5, Qt::AlignRight); item->setUserData((void *)this); setColors(std::move(txt), std::move(base)); } ~SyncViewItem() override { syncItemRef->setUserData(nullptr); } inline SynchronizerFileItem * synchronizerItemRef() { return syncItemRef; } inline SyncViewItem * lastItem() { return lastItemRef; } inline void setLastItem(SyncViewItem*s) { lastItemRef = s; } void setColors(const QColor& fore, const QColor& back) { QBrush textColor(fore); QBrush baseColor(back); for (int i = 0; i != columnCount(); i++) { if (back.isValid()) setBackground(i, baseColor); if (fore.isValid()) setForeground(i, textColor); } } }; public: // if rightDirectory is null, leftDirectory is actually the profile name to load SynchronizerGUI(QWidget* parent, QUrl leftDirectory, QUrl rightDirectory = QUrl(), QStringList selList = QStringList()); SynchronizerGUI(QWidget* parent, QString profile); ~SynchronizerGUI() override; inline bool wasSynchronization() { return wasSync; } public slots: void rightMouseClicked(QTreeWidgetItem *, const QPoint &); void doubleClicked(QTreeWidgetItem *); void compare(); void synchronize(); void stop(); void feedToListBox(); void closeDialog(); void refresh(); void swapSides(); void loadFromProfile(const QString&); void saveToProfile(const QString&); protected slots: - void reject() Q_DECL_OVERRIDE; + void reject() override; void addFile(SynchronizerFileItem *); void markChanged(SynchronizerFileItem *, bool); void setScrolling(bool); void statusInfo(const QString&); void subdirsChecked(bool); void setPanelLabels(); void setCompletion(); void checkExcludeURLValidity(QString &text, QString &error); void connectFilters(const QString &); private: void initGUI(const QString& profile, QUrl leftURL, QUrl rightURL, QStringList selList); QString convertTime(time_t time) const; void setMarkFlags(); void disableMarkButtons(); void enableMarkButtons(); void copyToClipboard(bool isLeft); int convertToSeconds(int time, int unit); void convertFromSeconds(int &time, int &unit, int second); static QPushButton *createButton(QWidget *parent, const QString &iconName, bool checked, const QKeySequence &shortCut, const QString &description, const QString &text = QString(), bool textAndIcon = false); protected: - void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; - bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *) override; + bool eventFilter(QObject *, QEvent *) override; void executeOperation(SynchronizerFileItem *item, int op); ProfileManager *profileManager; FilterTabs *filterTabs; GeneralFilter *generalFilter; QTabWidget *synchronizerTabs; KHistoryComboBox *leftLocation; KHistoryComboBox *rightLocation; KHistoryComboBox *fileFilter; KrTreeWidget *syncList; Synchronizer synchronizer; QCheckBox *cbSubdirs; QCheckBox *cbSymlinks; QCheckBox *cbByContent; QCheckBox *cbIgnoreDate; QCheckBox *cbAsymmetric; QCheckBox *cbIgnoreCase; QPushButton *btnSwapSides; QPushButton *btnCompareDirs; QPushButton *btnStopComparing; QPushButton *btnSynchronize; QPushButton *btnFeedToListBox; QPushButton *btnScrollResults; QPushButton *btnLeftToRight; QPushButton *btnEquals; QPushButton *btnDifferents; QPushButton *btnRightToLeft; QPushButton *btnDeletable; QPushButton *btnDuplicates; QPushButton *btnSingles; QLabel *statusLabel; QLabel *leftDirLabel; QLabel *rightDirLabel; QStringList selectedFiles; QSpinBox *parallelThreadsSpinBox; QSpinBox *equalitySpinBox; QComboBox *equalityUnitCombo; QSpinBox *timeShiftSpinBox; QComboBox *timeShiftUnitCombo; QCheckBox *ignoreHiddenFilesCB; private: static QString dirLabel(); // returns translated '' bool isComparing; bool wasClosed; bool wasSync; bool hasSelectedFiles; SyncViewItem *lastItem; QColor foreGrounds[ TT_MAX ]; QColor backGrounds[ TT_MAX ]; }; #endif /* __SYNCHRONIZERGUI_H__ */ diff --git a/krusader/Synchronizer/synchronizertask.h b/krusader/Synchronizer/synchronizertask.h index 66c83de2..cc91f469 100644 --- a/krusader/Synchronizer/synchronizertask.h +++ b/krusader/Synchronizer/synchronizertask.h @@ -1,190 +1,190 @@ /***************************************************************************** * Copyright (C) 2006 Csaba Karai * * Copyright (C) 2006-2019 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 SYNCHRONIZERTASK_H #define SYNCHRONIZERTASK_H // QtCore #include #include class Synchronizer; class SynchronizerDirList; class SynchronizerFileItem; class QTimer; class QFile; #define ST_STATE_NEW 0 #define ST_STATE_PENDING 1 #define ST_STATE_STATUS 2 #define ST_STATE_READY 3 #define ST_STATE_ERROR 4 class SynchronizerTask : public QObject { Q_OBJECT public: SynchronizerTask() : m_state(ST_STATE_NEW), m_statusMessage(QString()) {} ~SynchronizerTask() override = default; inline int start(QWidget *parentWidget) { this->parentWidget = parentWidget; start(); return state(); } inline int state() { return m_state; } void setStatusMessage(const QString & statMsg) { if (m_state == ST_STATE_PENDING || m_state == ST_STATE_STATUS) m_state = ST_STATE_STATUS; m_statusMessage = statMsg; } QString status() { if (m_state == ST_STATE_STATUS) { m_state = ST_STATE_PENDING; return m_statusMessage; } return QString(); } protected: virtual void start() {} int m_state; QString m_statusMessage; QWidget *parentWidget; }; class CompareTask : public SynchronizerTask { Q_OBJECT public: CompareTask(SynchronizerFileItem *parentIn, const QString &leftURL, const QString &rightURL, const QString &leftDir, const QString &rightDir, bool ignoreHidden); CompareTask(SynchronizerFileItem *parentIn, const QString &urlIn, const QString &dirIn, bool isLeftIn, bool ignoreHidden); ~CompareTask() override; inline bool isDuplicate() { return m_duplicate; } inline bool isLeft() { return !m_duplicate && m_isLeft; } inline const QString & leftURL() { return m_url; } inline const QString & rightURL() { return m_otherUrl; } inline const QString & leftDir() { return m_dir; } inline const QString & rightDir() { return m_otherDir; } inline const QString & url() { return m_url; } inline const QString & dir() { return m_dir; } inline SynchronizerFileItem * parent() { return m_parent; } inline SynchronizerDirList * leftDirList() { return m_dirList; } inline SynchronizerDirList * rightDirList() { return m_otherDirList; } inline SynchronizerDirList * dirList() { return m_dirList; } protected slots: - void start() Q_DECL_OVERRIDE; + void start() override; void slotFinished(bool result); void slotOtherFinished(bool result); private: SynchronizerFileItem * m_parent; QString m_url; QString m_dir; QString m_otherUrl; QString m_otherDir; bool m_isLeft; bool m_duplicate; SynchronizerDirList * m_dirList; SynchronizerDirList * m_otherDirList; bool m_loadFinished; bool m_otherLoadFinished; bool ignoreHidden; }; class CompareContentTask : public SynchronizerTask { Q_OBJECT public: CompareContentTask(Synchronizer *, SynchronizerFileItem *, const QUrl &, const QUrl &, KIO::filesize_t); ~CompareContentTask() override; public slots: void slotDataReceived(KIO::Job *job, const QByteArray &data); void slotFinished(KJob *job); void sendStatusMessage(); protected: - void start() Q_DECL_OVERRIDE; + void start() override; protected slots: void localFileCompareCycle(); private: void abortContentComparing(); QUrl leftURL; // the currently processed URL (left) QUrl rightURL; // the currently processed URL (right) KIO::filesize_t size; // the size of the compared files bool errorPrinted; // flag indicates error KIO::TransferJob *leftReadJob; // compare left read job KIO::TransferJob *rightReadJob; // compare right read job QByteArray compareArray; // the array for comparing int owner; // the owner of the compare array SynchronizerFileItem *item; // the item for content compare QTimer *timer; // timer to show the process dialog at compare by content QFile *leftFile; // the left side local file QFile *rightFile; // the right side local file KIO::filesize_t received; // the received size Synchronizer *sync; }; #endif /* __SYNCHRONIZER_TASK_H__ */ diff --git a/krusader/UserAction/expander.cpp b/krusader/UserAction/expander.cpp index 9db4e26e..b5505c32 100644 --- a/krusader/UserAction/expander.cpp +++ b/krusader/UserAction/expander.cpp @@ -1,1222 +1,1222 @@ /***************************************************************************** * Copyright (C) 2004 Jonas Bähr * * Copyright (C) 2004 Shie Erlich * * Copyright (C) 2004-2019 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 "expander.h" #include "../krusader.h" #include "../krusaderview.h" #include "../panelmanager.h" #include "../Panel/listpanel.h" #include "../Panel/panelfunc.h" #include "../Panel/PanelView/krview.h" #include "../Search/krsearchdialog.h" #include "../GUI/profilemanager.h" #include "../FileSystem/filesystemprovider.h" #include "../KViewer/krviewer.h" #include "../krservices.h" #ifdef SYNCHRONIZER_ENABLED #include "../Synchronizer/synchronizergui.h" #endif #ifdef __KJSEMBED__ #include "../KrJS/krjs.h" #endif // QtCore #include #include #include #include #include // QtGui #include // QtWidgets #include #include #include #include #include #include using namespace std; #define NEED_PANEL if (panel==0) { panelMissingError(_expression,exp); return QString(); } inline void exp_placeholder::setError(Expander& exp, const Error& e) { exp.setError(e); } inline QStringList exp_placeholder::splitEach(const TagString& s) { return Expander::splitEach(s); } inline exp_placeholder::exp_placeholder() = default; void exp_placeholder::panelMissingError(const QString &s, Expander& exp) { exp.setError(Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Needed panel specification missing in expander %1", s))); } QStringList exp_placeholder::fileList(const KrPanel* const panel, const QString& type, const QString& mask, const bool omitPath, const bool useUrl, Expander& exp, const QString& error) { QStringList items; if (type.isEmpty() || type == "all") panel->view->getItemsByMask(mask, &items); else if (type == "files") panel->view->getItemsByMask(mask, &items, false, true); else if (type == "dirs") panel->view->getItemsByMask(mask, &items, true, false); else if (type == "selected") panel->view->getSelectedItems(&items); else { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: Bad argument to %1: %2 is not valid item specifier", error, type))); return QStringList(); } if (!omitPath) { // add the current path // translate to urls using filesystem QList list = panel->func->files()->getUrls(items); items.clear(); // parse everything to a single qstring foreach(const QUrl &url, list) { items.push_back(useUrl ? url.url() : url.path()); } } return items; } namespace { class exp_simpleplaceholder : public exp_placeholder { public: - EXP_FUNC Q_DECL_OVERRIDE; + EXP_FUNC override; virtual TagString expFunc(const KrPanel*, const QStringList&, const bool&, Expander&) const = 0; }; #define PLACEHOLDER_CLASS(name) \ class name : public exp_placeholder { \ public: \ name(); \ - virtual TagString expFunc ( const KrPanel*, const TagStringList&, const bool&, Expander& ) const Q_DECL_OVERRIDE; \ + virtual TagString expFunc ( const KrPanel*, const TagStringList&, const bool&, Expander& ) const override; \ }; #define SIMPLE_PLACEHOLDER_CLASS(name) \ class name : public exp_simpleplaceholder { \ public: \ using exp_simpleplaceholder::expFunc; \ name(); \ - virtual TagString expFunc ( const KrPanel*, const QStringList&, const bool&, Expander& ) const Q_DECL_OVERRIDE; \ + virtual TagString expFunc ( const KrPanel*, const QStringList&, const bool&, Expander& ) const override; \ }; /** * expands %_Path% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the path of the specified panel */ SIMPLE_PLACEHOLDER_CLASS(exp_Path) /** * expands %_Count% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the number of items, which type is specified by the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_Count) /** * expands %_Filter% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the correspondent filter (ie: "*.cpp") */ SIMPLE_PLACEHOLDER_CLASS(exp_Filter) /** * expands %_Current% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with the current item ( != the selected ones) */ SIMPLE_PLACEHOLDER_CLASS(exp_Current); /** * expands %_List% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate the active, other, right or left panel) with a list of items, which type is specified by the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_List); /** * expands %_ListFile% ('_' is replaced by 'a', 'o', 'r' or 'l' to indicate * the active, other, right or left panel) with the name of a temporary file, * containing a list of items, which type is specified by the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_ListFile); /** * expands %_Ask% ('_' is necessary because there is no panel needed) * with the return of an input-dialog */ SIMPLE_PLACEHOLDER_CLASS(exp_Ask); /** * This copies it's first Parameter to the clipboard */ PLACEHOLDER_CLASS(exp_Clipboard); /** * This selects all items by the mask given with the first Parameter */ SIMPLE_PLACEHOLDER_CLASS(exp_Select); /** * This changes the panel'spath to the value given with the first Parameter. */ SIMPLE_PLACEHOLDER_CLASS(exp_Goto); /** * This is equal to 'cp '. */ PLACEHOLDER_CLASS(exp_Copy); /** * This is equal to 'mv '. */ PLACEHOLDER_CLASS(exp_Move); #ifdef SYNCHRONIZER_ENABLED /** * This opens the synchronizer with a given profile */ SIMPLE_PLACEHOLDER_CLASS(exp_Sync); #endif /** * This opens the searchmodule with a given profile */ SIMPLE_PLACEHOLDER_CLASS(exp_NewSearch); /** * This loads the panel-profile with a given name */ SIMPLE_PLACEHOLDER_CLASS(exp_Profile); /** * This is setting marks in the string where he is later split up for each {all, selected, files, dirs} */ SIMPLE_PLACEHOLDER_CLASS(exp_Each); /** * This sets the sorting on a specific column */ SIMPLE_PLACEHOLDER_CLASS(exp_ColSort); /** * This sets relation between the left and right panel */ SIMPLE_PLACEHOLDER_CLASS(exp_PanelSize); #ifdef __KJSEMBED__ /** * This sets relation between the left and right panel */ SIMPLE_PLACEHOLDER_CLASS(exp_Script); #endif /** * This loads a file in the internal viewer */ SIMPLE_PLACEHOLDER_CLASS(exp_View); //////////////////////////////////////////////////////////// //////////////////////// utils //////////////////////// //////////////////////////////////////////////////////////// /** * escapes everything that confuses bash in filenames * @param s String to manipulate * @return escaped string */ QString bashquote(QString s) { /* // we _can_not_ use this function because it _encloses_ the sting in single-quotes! // In this case quotes strings could not be concatenated anymore return KrServices::quote(s); */ static const QString evilstuff = "\\\"'`()[]{}!?;$&<>| \t\r\n"; // stuff that should get escaped for (auto i : evilstuff) s.replace(i, ('\\' + i)); return s; } QString separateAndQuote(QStringList list, const QString& separator, const bool quote) { if (quote) transform(list.begin(), list.end(), list.begin(), bashquote); // QLineEdit::text() always escapes special characters, revert this for newline and tab QString decodedSeparator = separator; decodedSeparator.replace("\\n", "\n").replace("\\t", "\t"); return list.join(decodedSeparator); } ///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// expander classes //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// exp_Path::exp_Path() { _expression = "Path"; _description = i18n("Panel's Path..."); _needPanel = true; addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_Path::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL QString result; if (useUrl) result = panel->func->files()->currentDirectory().url() + '/'; else result = panel->func->files()->currentDirectory().path() + '/'; if (parameter.count() > 0 && parameter[0].toLower() == "no") // don't escape spaces return TagString(result); else return TagString(bashquote(result)); } exp_Count::exp_Count() { _expression = "Count"; _description = i18n("Number of..."); _needPanel = true; addParameter(exp_parameter(i18n("Count:"), "__choose:All;Files;Dirs;Selected", false)); } TagString exp_Count::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL int n = -1; if (parameter.count() == 0 || parameter[ 0 ].isEmpty() || parameter[ 0 ].toLower() == "all") n = panel->view->numDirs() + panel->view->numFiles(); else if (parameter[ 0 ].toLower() == "files") n = panel->view->numFiles(); else if (parameter[ 0 ].toLower() == "dirs") n = panel->view->numDirs(); else if (parameter[ 0 ].toLower() == "selected") n = panel->view->numSelected(); else { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: Bad argument to Count: %1 is not valid item specifier", parameter[0]))); return QString(); } return TagString(QString("%1").arg(n)); } exp_Filter::exp_Filter() { _expression = "Filter"; _description = i18n("Filter Mask (*.h, *.cpp, etc.)"); _needPanel = true; } TagString exp_Filter::expFunc(const KrPanel* panel, const QStringList&, const bool&, Expander& exp) const { NEED_PANEL return panel->view->filterMask().nameFilter(); } exp_Current::exp_Current() { _expression = "Current"; _description = i18n("Current File (!= Selected File)..."); _needPanel = true; addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_Current::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL QString item = panel->view->getCurrentItem(); if (item == "..") { // if ".." is current, treat this as nothing is current return QString(); } QString result; if (parameter.count() > 0 && parameter[0].toLower() == "yes") // omit the current path result = item; else { const QUrl url = panel->func->files()->getUrl(item); result = useUrl ? url.url() : url.path(); } const bool escapeSpaces = parameter.count() < 2 || parameter[1].toLower() != "no"; return escapeSpaces ? bashquote(result) : result; } exp_List::exp_List() { _expression = "List"; _description = i18n("Item List of..."); _needPanel = true; addParameter(exp_parameter(i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false)); addParameter(exp_parameter(i18n("Separator between the items (optional):"), " ", false)); addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Mask (optional, all but 'Selected'):"), "__select", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_List::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL // get selected items from view QStringList items; QString mask; if (parameter.count() <= 3 || parameter[3].isEmpty()) mask = '*'; else mask = parameter[3]; return separateAndQuote( fileList(panel, parameter.isEmpty() ? QString() : parameter[0].toLower(), mask, parameter.count() > 2 ? parameter[2].toLower() == "yes" : false, useUrl, exp, "List"), parameter.count() > 1 ? parameter[1] : " ", parameter.count() > 4 ? parameter[4].toLower() == "yes" : true); } exp_ListFile::exp_ListFile() { _expression = "ListFile"; _description = i18n("Filename of an Item List..."); _needPanel = true; addParameter(exp_parameter(i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false)); addParameter(exp_parameter(i18n("Separator between the items (optional)"), "\n", false)); addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Mask (optional, all but 'Selected'):"), "__select", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__no", false)); } TagString exp_ListFile::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL // get selected items from view QStringList items; QString mask; if (parameter.count() <= 3 || parameter[3].isEmpty()) mask = '*'; else mask = parameter[3]; QTemporaryFile tmpFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.itemlist")); tmpFile.setAutoRemove(false); if (!tmpFile.open()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_WORLD, i18n("Expander: temporary file could not be opened (%1)", tmpFile.errorString()))); return QString(); } QTextStream stream(&tmpFile); stream << separateAndQuote( fileList(panel, parameter.isEmpty() ? QString() : parameter[0].toLower(), mask, parameter.count() > 2 ? parameter[2].toLower() == "yes" : false, useUrl, exp, "ListFile"), parameter.count() > 1 ? parameter[1] : "\n", parameter.count() > 4 ? parameter[4].toLower() == "yes" : true) << "\n"; tmpFile.close(); return tmpFile.fileName(); } exp_Select::exp_Select() { _expression = "Select"; _description = i18n("Manipulate the Selection..."); _needPanel = true; addParameter(exp_parameter(i18n("Selection mask:"), "__select", true)); addParameter(exp_parameter(i18n("Manipulate in which way:"), "__choose:Set;Add;Remove", false)); } TagString exp_Select::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& , Expander& exp) const { NEED_PANEL KRQuery mask; if (parameter.count() <= 0 || parameter[0].isEmpty()) mask = KRQuery("*"); else mask = KRQuery(parameter[0]); if (parameter.count() > 1 && parameter[1].toLower() == "list-add") panel->view->select(mask); else if (parameter.count() > 1 && parameter[1].toLower() == "list-remove") panel->view->unselect(mask); else { // parameter[1].toLower() == "set" or isEmpty() or whatever panel->view->unselect(KRQuery("*")); panel->view->select(mask); } return QString(); // this doesn't return anything, that's normal! } exp_Goto::exp_Goto() { _expression = "Goto"; _description = i18n("Jump to a Location..."); _needPanel = true; addParameter(exp_parameter(i18n("Choose a path:"), "__goto", true)); addParameter(exp_parameter(i18n("Open location in a new tab"), "__no", false)); } TagString exp_Goto::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL bool newTab = false; if (parameter.count() > 1 && parameter[1].toLower() == "yes") newTab = true; if (parameter.count() == 0) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 1 parameter is required for Goto."))); return QString(); } QUrl url = QUrl::fromUserInput(parameter[0], QString(), QUrl::AssumeLocalFile); if (newTab) { if (panel == LEFT_PANEL) MAIN_VIEW->leftManager()->slotNewTab(url); else MAIN_VIEW->rightManager()->slotNewTab(url); } else { panel->func->openUrl(url, ""); panel->gui->slotFocusOnMe(); } return QString(); // this doesn't return anything, that's normal! } /* exp_Search::exp_Search() { _expression = "Search"; _description = i18n("Search for files"); _needPanel = true; addParameter( new exp_parameter( i18n("please choose the setting"), "__searchprofile", true ) ); addParameter( new exp_parameter( i18n("open the search in a new tab"), "__yes", false ) ); //TODO: add this also to panel-dependent as soon as filesystem support the display of search-results } */ exp_Ask::exp_Ask() { _expression = "Ask"; _description = i18n("Ask Parameter from User..."); _needPanel = false; addParameter(exp_parameter(i18n("Question:"), "Where do you want do go today?", true)); addParameter(exp_parameter(i18n("Preset (optional):"), "", false)); addParameter(exp_parameter(i18n("Caption (optional):"), "", false)); } TagString exp_Ask::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { QString caption, preset, result; if (parameter.count() == 0) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 1 parameter is required for Ask."))); return QString(); } if (parameter.count() <= 2 || parameter[2].isEmpty()) caption = i18n("User Action"); else caption = parameter[2]; if (parameter.count() <= 1 || parameter[1].isEmpty()) preset.clear(); else preset = parameter[1]; bool ok; result = QInputDialog::getText(krMainWindow, caption, parameter[0], QLineEdit::Normal, preset, &ok); if (ok) return result; else { // user cancelled setError(exp, Error(Error::exp_S_ERROR, Error::exp_C_USER)); return QString(); } } exp_Clipboard::exp_Clipboard() { _expression = "Clipboard"; _description = i18n("Copy to Clipboard..."); _needPanel = false; addParameter(exp_parameter(i18n("What to copy:"), "__placeholder", true)); addParameter(exp_parameter(i18n("Append to current clipboard content with this separator (optional):"), "", false)); } TagString exp_Clipboard::expFunc(const KrPanel*, const TagStringList& parameter, const bool&, Expander& exp) const { // qDebug() << "Expander::exp_Clipboard, parameter[0]: '" << parameter[0] << "', Clipboard: " << QApplication::clipboard()->text(); if (parameter.count() == 0) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 1 parameter is required for Clipboard."))); return QString(); } QStringList lst = splitEach(parameter[0]); if (parameter.count() > 1 && !parameter[1].isSimple()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Expander: %Each% may not be in the second argument of %Clipboard%"))); return QString(); } if (parameter.count() <= 1 || parameter[1].string().isEmpty() || QApplication::clipboard()->text().isEmpty()) QApplication::clipboard()->setText(lst.join("\n")); else QApplication::clipboard()->setText(QApplication::clipboard()->text() + parameter[1].string() + lst.join("\n")); return QString(); // this doesn't return anything, that's normal! } exp_Copy::exp_Copy() { _expression = "Copy"; _description = i18n("Copy a File/Folder..."); _needPanel = false; addParameter(exp_parameter(i18n("What to copy:"), "__placeholder", true)); addParameter(exp_parameter(i18n("Where to copy:"), "__placeholder", true)); } TagString exp_Copy::expFunc(const KrPanel*, const TagStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() < 2) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 2 parameter is required for Copy."))); return QString(); } // basically the parameter can already be used as URL, but since QUrl has problems with ftp-proxy-urls (like ftp://username@proxyusername@url...) this is necessary: const QStringList sourceList = splitEach(parameter[0]); QList sourceURLs; for (const QString& source : sourceList) { sourceURLs.append(QUrl::fromUserInput(source, QString(), QUrl::AssumeLocalFile)); } if (!parameter[1].isSimple()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Expander: %Each% may not be in the second argument of %Copy%"))); return QString(); } // or transform(...) ? const QUrl dest = QUrl::fromUserInput(parameter[1].string(), QString(), QUrl::AssumeLocalFile); if (!dest.isValid() || find_if(sourceURLs.constBegin(), sourceURLs.constEnd(), not1(mem_fun_ref(&QUrl::isValid))) != sourceURLs.constEnd()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: invalid URLs in %_Copy(\"src\", \"dest\")%"))); return QString(); } FileSystemProvider::instance().startCopyFiles(sourceURLs, dest); return QString(); // this doesn't return everything, that's normal! } exp_Move::exp_Move() { _expression = "Move"; _description = i18n("Move/Rename a File/Folder..."); _needPanel = false; addParameter(exp_parameter(i18n("What to move/rename:"), "__placeholder", true)); addParameter(exp_parameter(i18n("New target/name:"), "__placeholder", true)); } TagString exp_Move::expFunc(const KrPanel*, const TagStringList& parameter, const bool& , Expander& exp) const { if (parameter.count() < 2) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: at least 2 parameter is required for Move."))); return QString(); } // basically the parameter can already be used as URL, but since QUrl has problems with ftp-proxy-urls (like ftp://username@proxyusername@url...) this is necessary: QStringList lst = splitEach(parameter[0]); if (!parameter[1].isSimple()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("%Each% may not be in the second argument of %Move%"))); return QString(); } QList src; for (QStringList::const_iterator it = lst.constBegin(), end = lst.constEnd();it != end;++it) src.push_back(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); // or transform(...) ? QUrl dest = QUrl::fromUserInput(parameter[1].string(), QString(), QUrl::AssumeLocalFile); if (!dest.isValid() || find_if(src.constBegin(), src.constEnd(), not1(mem_fun_ref(&QUrl::isValid))) != src.constEnd()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: invalid URLs in %_Move(\"src\", \"dest\")%"))); return QString(); } FileSystemProvider::instance().startCopyFiles(src, dest, KIO::CopyJob::Move); return QString(); // this doesn't return anything, that's normal! } #ifdef SYNCHRONIZER_ENABLED exp_Sync::exp_Sync() { _expression = "Sync"; _description = i18n("Load a Synchronizer Profile..."); _needPanel = false; addParameter(exp_parameter(i18n("Choose a profile:"), "__syncprofile", true)); } TagString exp_Sync::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no profile specified for %_Sync(profile)%"))); return QString(); } SynchronizerGUI *synchronizerDialog = new SynchronizerGUI(MAIN_VIEW, parameter[0]); synchronizerDialog->show(); // destroyed on close return QString(); // this doesn't return everything, that's normal! } #endif exp_NewSearch::exp_NewSearch() { _expression = "NewSearch"; _description = i18n("Load a Searchmodule Profile..."); _needPanel = false; addParameter(exp_parameter(i18n("Choose a profile:"), "__searchprofile", true)); } TagString exp_NewSearch::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no profile specified for %_NewSearch(profile)%"))); return QString(); } new KrSearchDialog(parameter[0], krApp); return QString(); // this doesn't return everything, that's normal! } exp_Profile::exp_Profile() { _expression = "Profile"; _description = i18n("Load a Panel Profile..."); _needPanel = false; addParameter(exp_parameter(i18n("Choose a profile:"), "__panelprofile", true)); } TagString exp_Profile::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no profile specified for %_Profile(profile)%; abort..."))); return QString(); } MAIN_VIEW->profiles(parameter[0]); return QString(); // this doesn't return everything, that's normal! } exp_Each::exp_Each() { _expression = "Each"; _description = i18n("Separate Program Call for Each..."); _needPanel = true; addParameter(exp_parameter(i18n("Which items:"), "__choose:All;Files;Dirs;Selected", false)); addParameter(exp_parameter(i18n("Omit the current path (optional)"), "__no", false)); addParameter(exp_parameter(i18n("Mask (optional, all but 'Selected'):"), "__select", false)); addParameter(exp_parameter(i18n("Automatically escape spaces"), "__yes", false)); } TagString exp_Each::expFunc(const KrPanel* panel, const QStringList& parameter, const bool& useUrl, Expander& exp) const { NEED_PANEL QString mask; if (parameter.count() <= 2 || parameter[2].isEmpty()) mask = '*'; else mask = parameter[2]; TagString ret; QStringList l = fileList(panel, parameter.empty() ? QString() : parameter[0].toLower(), mask, parameter.count() > 1 && parameter[1].toLower() == "yes", useUrl, exp, "Each"); if (!(parameter.count() <= 3 || parameter[3].toLower() != "yes")) transform(l.begin(), l.end(), l.begin(), bashquote); ret.insertTag(0, l); return ret; } exp_ColSort::exp_ColSort() { _expression = "ColSort"; _description = i18n("Set Sorting for This Panel..."); _needPanel = true; addParameter(exp_parameter(i18n("Choose a column:"), "__choose:Name;Ext;Type;Size;Modified;Perms;rwx;Owner;Group", true)); addParameter(exp_parameter(i18n("Choose a sort sequence:"), "__choose:Toggle;Asc;Desc", false)); } TagString exp_ColSort::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no column specified for %_ColSort(column)%"))); return QString(); } KrViewProperties::ColumnType oldColumn = panel->view->properties()->sortColumn; KrViewProperties::ColumnType column = oldColumn; if (parameter[0].toLower() == "name") { column = KrViewProperties::Name; } else if (parameter[0].toLower() == "ext") { column = KrViewProperties::Ext; } else if (parameter[0].toLower() == "type") { column = KrViewProperties::Type; } else if (parameter[0].toLower() == "size") { column = KrViewProperties::Size; } else if (parameter[0].toLower() == "modified") { column = KrViewProperties::Modified; } else if (parameter[0].toLower() == "changed") { column = KrViewProperties::Changed; } else if (parameter[0].toLower() == "accessed") { column = KrViewProperties::Accessed; } else if (parameter[0].toLower() == "perms") { column = KrViewProperties::Permissions; } else if (parameter[0].toLower() == "rwx") { column = KrViewProperties::KrPermissions; } else if (parameter[0].toLower() == "owner") { column = KrViewProperties::Owner; } else if (parameter[0].toLower() == "group") { column = KrViewProperties::Group; } else { setError(exp, Error(Error::exp_S_WARNING, Error::exp_C_ARGUMENT, i18n("Expander: unknown column specified for %_ColSort(%1)%", parameter[0]))); return QString(); } bool descending = panel->view->properties()->sortOptions & KrViewProperties::Descending; if (parameter.count() <= 1 || (parameter[1].toLower() != "asc" && parameter[1].toLower() != "desc")) { // no sortdir parameter if(column == oldColumn) // reverse direction if column is unchanged descending = !descending; else // otherwise set to ascending descending = false; } else { // sortdir specified if (parameter[1].toLower() == "asc") descending = false; else // == desc descending = true; } panel->view->setSortMode(column, descending); return QString(); // this doesn't return anything, that's normal! } exp_PanelSize::exp_PanelSize() { _expression = "PanelSize"; _description = i18n("Set Relation Between the Panels..."); _needPanel = true; addParameter(exp_parameter(i18n("Set the new size in percent:"), "__int:0;100;5;50", true)); } TagString exp_PanelSize::expFunc(const KrPanel* panel, const QStringList& parameter, const bool&, Expander& exp) const { NEED_PANEL int newSize; if (parameter.count() == 0 || parameter[0].isEmpty()) newSize = 50; //default is 50% else newSize = parameter[0].toInt(); if (newSize < 0 || newSize > 100) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: Value %1 out of range for %_PanelSize(percent)%. The first parameter has to be >0 and <100", newSize))); return QString(); } MAIN_VIEW->setPanelSize(panel->isLeft(), newSize); return QString(); // this doesn't return everything, that's normal! } #ifdef __KJSEMBED__ exp_Script::exp_Script() { _expression = "Script"; _description = i18n("Execute a JavaScript Extension..."); _needPanel = false; addParameter(exp_parameter(i18n("Location of the script"), "", true)); addParameter(exp_parameter(i18n("Set some variables for the execution (optional).\ni.e. \"return=return_var;foo=bar\", consult the handbook for more information"), "", false)); } TagString exp_Script::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no script specified for %_Script(script)%"))); return QString(); } QString filename = parameter[0]; if (filename.find('/') && QUrl::isRelativeUrl(filename)) { // this return the local version of the file if this exists. else the global one is returnd filename = locate("data", "krusader/js/" + filename); } if (! krJS) krJS = new KrJS(); KJS::ExecState *exec = krJS->globalExec(); QString jsReturn; if (parameter[1].toLower() == "yes") // to stay compatible with the old-style parameter jsReturn = "cmd"; else { QStringList jsVariables = parameter[1].split(';'); QString jsVariable, jsValue; for (QStringList::Iterator it = jsVariables.begin(); it != jsVariables.end(); ++it) { jsVariable = (*it).section('=', 0, 0).trimmed(); jsValue = (*it).section('=', 1); if (jsVariable == "return") jsReturn = jsValue.trimmed(); else krJS->putValue(jsVariable, KJSEmbed::convertToValue(exec, jsValue)); } } krJS->runFile(filename); if (! jsReturn.isEmpty()) return krJS->getValue(jsReturn).toString(krJS->globalExec()).qstring(); else return QString(); } #endif exp_View::exp_View() { _expression = "View"; _description = i18n("View File with Krusader's Internal Viewer..."); _needPanel = false; addParameter(exp_parameter(i18n("Which file to view (normally '%aCurrent%'):"), "__placeholder", true)); addParameter(exp_parameter(i18n("Choose a view mode:"), "__choose:generic;text;hex", false)); //addParameter( exp_parameter( i18n("Choose a window-mode"), "__choose:tab;window;panel", false ) ); //TODO: window-mode 'panel' should open the file in the third-hand viewer addParameter(exp_parameter(i18n("Choose a window mode:"), "__choose:tab;window", false)); } TagString exp_View::expFunc(const KrPanel*, const QStringList& parameter, const bool&, Expander& exp) const { if (parameter.count() == 0 || parameter[0].isEmpty()) { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_ARGUMENT, i18n("Expander: no file to view in %_View(filename)%"))); return QString(); } QString viewMode, windowMode; if (parameter.count() <= 1 || parameter[1].isEmpty()) viewMode = "generic"; else viewMode = parameter[1]; if (parameter.count() <= 2 || parameter[2].isEmpty()) windowMode = "tab"; else windowMode = parameter[2]; KrViewer::Mode mode = KrViewer::Generic; if (viewMode == "text") mode = KrViewer::Text; else if (viewMode == "hex") mode = KrViewer::Hex; QUrl url = QUrl::fromUserInput(parameter[0], QString(), QUrl::AssumeLocalFile); KrViewer::view(url, mode, (windowMode == "window")); //TODO: Call the viewer with viewMode and windowMode. Filename is in parameter[0]. // It would be nice if parameter[0] could also be a space-separated filename-list (provided if the first parameter is %aList(selected)%) return QString(); // this doesn't return everything, that's normal! } ///////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// end of expander classes //////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// TagString exp_simpleplaceholder::expFunc(const KrPanel* p, const TagStringList& parameter, const bool& useUrl, Expander& exp) const { QStringList lst; for (const auto & it : parameter) if (it.isSimple()) lst.push_back(it.string()); else { setError(exp, Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("%Each% is not allowed in parameter to %1", description()))); return QString(); } return expFunc(p, lst, useUrl, exp); } } KrPanel* Expander::getPanel(const char panelIndicator, const exp_placeholder* pl, Expander& exp) { switch (panelIndicator) { case 'a': return ACTIVE_PANEL; case 'o': return OTHER_PANEL; case 'l': return LEFT_PANEL; case 'r': return RIGHT_PANEL; case '_': return nullptr; default: exp.setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Expander: Bad panel specifier %1 in placeholder %2", panelIndicator, pl->description()))); return nullptr; } } void Expander::expand(const QString& stringToExpand, bool useUrl) { TagString result = expandCurrent(stringToExpand, useUrl); if (error()) return; if (!result.isSimple()) resultList = splitEach(result); else resultList.append(result.string()); // qWarning() << resultList[0]; } TagString Expander::expandCurrent(const QString& stringToExpand, bool useUrl) { TagString result; QString exp; TagString tmpResult; int begin, end, i; // int brackets = 0; // bool inQuotes = false; int idx = 0; while (idx < stringToExpand.length()) { if ((begin = stringToExpand.indexOf('%', idx)) == -1) break; if ((end = findEnd(stringToExpand, begin)) == -1) { // xgettext:no-c-format setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Error: unterminated % in Expander"))); return QString(); } result += stringToExpand.mid(idx, begin - idx); // copy until the start of %exp% // get the expression, and expand it using the correct expander function exp = stringToExpand.mid(begin + 1, end - begin - 1); // qDebug() << "------------- exp: '" << exp << "'"; if (exp.isEmpty()) result += QString(QChar('%')); else { TagStringList parameter = separateParameter(&exp, useUrl); if (error()) return QString(); char panelIndicator = exp.toLower()[0].toLatin1(); exp.replace(0, 1, ""); for (i = 0; i < placeholderCount(); ++i) if (exp == placeholder(i)->expression()) { // qDebug() << "---------------------------------------"; tmpResult = placeholder(i)->expFunc(getPanel(panelIndicator, placeholder(i), *this), parameter, useUrl, *this); if (error()) { return QString(); } else result += tmpResult; // qDebug() << "---------------------------------------"; break; } if (i == placeholderCount()) { // didn't find an expander setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Error: unrecognized %%%1%2%% in Expander", panelIndicator, exp))); return QString(); } } //else idx = end + 1; } // copy the rest of the string result += stringToExpand.mid(idx); // qDebug() << "============== result '" << result << "'"; return result; } QStringList Expander::splitEach(TagString stringToSplit) { if (stringToSplit.isSimple()) { // qWarning() << stringToSplit.string(); QStringList l; l << stringToSplit.string(); return l; } pair pl = *stringToSplit.tagsBegin(); stringToSplit.eraseTag(stringToSplit.tagsBegin()); QStringList ret; for (QStringList::const_iterator it = pl.second.constBegin(), end = pl.second.constEnd();it != end;++it) { TagString s = stringToSplit; s.insert(pl.first, *it); ret += splitEach(s); } return ret; // qDebug() << "stringToSplit: " << stringToSplit; } TagStringList Expander::separateParameter(QString* const exp, bool useUrl) { TagStringList parameter; QStringList parameter1; QString result; int begin, end; if ((begin = exp->indexOf('(')) != -1) { if ((end = exp->lastIndexOf(')')) == -1) { setError(Error(Error::exp_S_FATAL, Error::exp_C_SYNTAX, i18n("Error: missing ')' in Expander"))); return TagStringList(); } result = exp->mid(begin + 1, end - begin - 1); *exp = exp->left(begin); bool inQuotes = false; int idx = 0; begin = 0; while (idx < result.length()) { if (result[ idx ].toLatin1() == '\\') { if (result[ idx+1 ].toLatin1() == '"') result.replace(idx, 1, ""); } if (result[ idx ].toLatin1() == '"') inQuotes = !inQuotes; if (result[ idx ].toLatin1() == ',' && !inQuotes) { parameter1.append(result.mid(begin, idx - begin)); begin = idx + 1; // qWarning() << " ---- parameter: " << parameter.join(";"); } idx++; } parameter1.append(result.mid(begin, idx - begin)); //don't forget the last one for (auto & it : parameter1) { it = it.trimmed(); if (it.left(1) == "\"") it = it.mid(1, it.length() - 2); parameter.push_back(expandCurrent(it, useUrl)); if (error()) return TagStringList(); } } // qWarning() << "------- exp: " << *exp << " ---- parameter: " << parameter.join(";"); return parameter; } int Expander::findEnd(const QString& str, int start) { int end = str.indexOf('%', start + 1); if (end == -1) return end; int bracket = str.indexOf('(', start + 1); if (end < bracket || bracket == -1) return end; int idx = bracket + 1; bool inQuotes = false; int depth = 1; while (idx < str.length()) { switch (str[ idx ].toLatin1()) { case '\\': idx ++; break; case '"': inQuotes = !inQuotes; break; case '(': if (!inQuotes) depth++; break; case ')': if (!inQuotes) --depth; break; case '%': if (depth == 0) return idx; } //switch idx++; } //while // failsafe return -1; } QList& Expander::_placeholder() { static QList ret; if(!ret.count()) { ret << new exp_View; ret << new exp_PanelSize; ret << new exp_ColSort; ret << new exp_Each; ret << new exp_Profile; ret << new exp_NewSearch; #ifdef SYNCHRONIZER_ENABLED ret << new exp_Sync; #endif ret << new exp_Move; ret << new exp_Copy; ret << new exp_Goto; ret << new exp_Select; ret << new exp_Clipboard; ret << new exp_Ask; ret << new exp_ListFile; ret << new exp_List; ret << new exp_Current; ret << new exp_Filter; ret << new exp_Count; ret << new exp_Path; #ifdef __KJSEMBED__ ret << new exp_Script; #endif } return ret; } diff --git a/krusader/UserAction/kraction.h b/krusader/UserAction/kraction.h index 1ed07994..a013b521 100644 --- a/krusader/UserAction/kraction.h +++ b/krusader/UserAction/kraction.h @@ -1,250 +1,250 @@ /***************************************************************************** * Copyright (C) 2004 Shie Erlich * * Copyright (C) 2004 Rafi Yanai * * Copyright (C) 2006 Jonas Bähr * * Copyright (C) 2004-2019 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 KRACTION_H #define KRACTION_H // QtCore #include #include // QtGui #include // QtWidgets #include #include #include #include #include "kractionbase.h" class QDomDocument; class QDomElement; class KActionCollection; /** * This subclass of QAction extends it with an individual executor and * a struct UserActionProperties. * It is used to integrate useractions into KDE's QAction-System */ class KrAction: public QAction, public KrActionBase { Q_OBJECT public: explicit KrAction(KActionCollection *parent, const QString& name = QString()); ~KrAction() override; /** * This chekcs if the KrAction is for a specific file / location available * @param currentURL Check for this file * @return true if the KrAction if available */ bool isAvailable(const QUrl ¤tURL); const QString& iconName() const { return _iconName; } // TODO: added for kde4 porting (functionality is missing) void setIconName(const QString& name) { _iconName = name; } bool xmlRead(const QDomElement& element); QDomElement xmlDump(QDomDocument& doc) const; QString category() const { return _category; }; void setCategory(const QString& category) { _category = category; }; - QString command() const Q_DECL_OVERRIDE { + QString command() const override { return _command; }; void setCommand(const QString& command) { _command = command; }; - QString user() const Q_DECL_OVERRIDE { + QString user() const override { return _user; }; void setUser(const QString& user) { _user = user; }; - QString startpath() const Q_DECL_OVERRIDE { + QString startpath() const override { return _startpath; }; void setStartpath(const QString& startpath) { _startpath = startpath; }; - ExecType execType() const Q_DECL_OVERRIDE { + ExecType execType() const override { return _execType; }; void setExecType(ExecType execType) { _execType = execType; }; - bool acceptURLs() const Q_DECL_OVERRIDE { + bool acceptURLs() const override { return _acceptURLs; }; void setAcceptURLs(const bool& acceptURLs) { _acceptURLs = acceptURLs; }; - bool confirmExecution() const Q_DECL_OVERRIDE { + bool confirmExecution() const override { return _confirmExecution; }; void setConfirmExecution(const bool& confirmExecution) { _confirmExecution = confirmExecution; }; QStringList showonlyProtocol() const { return _showonlyProtocol; }; void setShowonlyProtocol(const QStringList& showonlyProtocol) { _showonlyProtocol = showonlyProtocol; }; QStringList showonlyPath() const { return _showonlyPath; }; void setShowonlyPath(const QStringList& showonlyPath) { _showonlyPath = showonlyPath; }; QStringList showonlyMime() const { return _showonlyMime; }; void setShowonlyMime(const QStringList& showonlyMime) { _showonlyMime = showonlyMime; }; QStringList showonlyFile() const { return _showonlyFile; }; void setShowonlyFile(const QStringList& showonlyFile) { _showonlyFile = showonlyFile; }; - bool doSubstitution() const Q_DECL_OVERRIDE { + bool doSubstitution() const override { return true; } - QString text() const Q_DECL_OVERRIDE { + QString text() const override { return QAction::text(); } public slots: void exec() { KrActionBase::exec(); } private: void readCommand(const QDomElement& element); QDomElement dumpCommand(QDomDocument& doc) const; void readAvailability(const QDomElement& element); QDomElement dumpAvailability(QDomDocument& doc) const; QString _iconName; QString _category; QString _command; QString _user; QString _startpath; ExecType _execType; bool _acceptURLs; bool _confirmExecution; QStringList _showonlyProtocol; QStringList _showonlyPath; QStringList _showonlyMime; QStringList _showonlyFile; KActionCollection *_actionCollection; }; /** * This displays the output of a process */ class KrActionProcDlg: public QDialog { Q_OBJECT public: explicit KrActionProcDlg(const QString& caption, bool enableStderr = false, QWidget *parent = nullptr); public slots: void addStderr(const QString& str); void addStdout(const QString& str); void slotProcessFinished(); protected slots: void toggleFixedFont(bool state); void slotSaveAs(); signals: void killClicked(); private: KTextEdit *_stdout; KTextEdit *_stderr; KTextEdit *_currentTextEdit; QFont normalFont; QFont fixedFont; QPushButton *closeButton; QPushButton *killButton; private slots: void currentTextEditChanged(); }; /** * This executes a command of a UserAction */ // TODO jonas: call a list of commands separately (I began it but it doesn't work) class KrActionProc: public QObject { Q_OBJECT public: explicit KrActionProc(KrActionBase* action); ~KrActionProc() override; void start(const QString& cmdLine); void start(QStringList cmdLineList); protected slots: void kill() { _proc->kill(); } void processExited(int exitCode, QProcess::ExitStatus exitStatus); void addStderr(); void addStdout(); private: KrActionBase* _action; KProcess *_proc; QString _stdout; QString _stderr; KrActionProcDlg *_output; }; #endif //KRACTION_H diff --git a/krusader/krusader.h b/krusader/krusader.h index e6e61c08..31da34df 100644 --- a/krusader/krusader.h +++ b/krusader/krusader.h @@ -1,187 +1,187 @@ /***************************************************************************** * Copyright (C) 2000 Shie Erlich * * Copyright (C) 2000 Rafi Yanai * * Copyright (C) 2004-2019 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 KRUSADER_H #define KRUSADER_H #ifdef HAVE_CONFIG_H #include #endif #include "krmainwindow.h" // QtCore #include #include #include #include #include // QtGui #include #include #include #include // QtWidgets #include #include #include #include #include #include #ifdef __KJSEMBED__ class KrJS; #endif class KStartupInfoData; class KStartupInfoId; class KrusaderStatus; class KRPleaseWaitHandler; class PopularUrls; class ViewActions; class ListPanelActions; class TabActions; class KrView; /** * @brief The main window of this file manager */ class Krusader : public KParts::MainWindow, public KrMainWindow { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.krusader.Instance") public: explicit Krusader(const QCommandLineParser &parser); ~Krusader() override; void setTray(bool forceCreation = false); // KrMainWindow implementation - QWidget *widget() Q_DECL_OVERRIDE { + QWidget *widget() override { return this; } - KrView *activeView() Q_DECL_OVERRIDE; - ViewActions *viewActions() Q_DECL_OVERRIDE { + KrView *activeView() override; + ViewActions *viewActions() override { return _viewActions; } - KActionCollection *actions() Q_DECL_OVERRIDE { + KActionCollection *actions() override { return actionCollection(); } - AbstractPanelManager *activeManager() Q_DECL_OVERRIDE; - AbstractPanelManager *leftManager() Q_DECL_OVERRIDE; - AbstractPanelManager *rightManager() Q_DECL_OVERRIDE; - PopularUrls *popularUrls() Q_DECL_OVERRIDE { + AbstractPanelManager *activeManager() override; + AbstractPanelManager *leftManager() override; + AbstractPanelManager *rightManager() override; + PopularUrls *popularUrls() override { return _popularUrls; } - KrActions *krActions() Q_DECL_OVERRIDE { + KrActions *krActions() override { return _krActions; } - ListPanelActions *listPanelActions() Q_DECL_OVERRIDE { + ListPanelActions *listPanelActions() override { return _listPanelActions; } - TabActions *tabActions() Q_DECL_OVERRIDE { + TabActions *tabActions() override { return _tabActions; } - void plugActionList(const char *name, QList &list) Q_DECL_OVERRIDE { + void plugActionList(const char *name, QList &list) override { KParts::MainWindow::plugActionList(name, list); } /** * Icon name that depends on whether krusader runs with root-privileges or not * * @return icon name */ static const char* appIconName(); public slots: void quit(); void moveToTop(); void statusBarUpdate(const QString& mess); // in use by Krusader only void saveSettings(); void savePosition(); void updateUserActions(); protected slots: void doOpenUrl(); void slotGotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data); void slotGotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data); protected: - void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; - void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; - bool queryClose() Q_DECL_OVERRIDE; + void closeEvent(QCloseEvent *event) override; + void showEvent(QShowEvent *event) override; + bool queryClose() override; void setupActions(); bool versionControl(); // handle version differences in krusaderrc - bool event(QEvent *) Q_DECL_OVERRIDE; + bool event(QEvent *) override; public Q_SLOTS: Q_SCRIPTABLE bool isRunning(); Q_SCRIPTABLE bool isLeftActive(); Q_SCRIPTABLE bool openUrl(QString url); public: static Krusader *App; // a kApp style pointer static QString AppName; // the name of the application PopularUrls *_popularUrls; // holds a sorted list of the most popular urls visited // the internal progress bar variales + functions KRPleaseWaitHandler* plzWait; void startWaiting(QString msg = "Please Wait", int count = 0 , bool cancel = false); void stopWait(); bool wasWaitingCancelled() const; #ifdef __KJSEMBED__ static KrJS *js; #endif signals: void changeMessage(QString); // emitted when we are about to quit void shutdown(); private: void acceptClose(); private: KrActions *_krActions; ViewActions *_viewActions; ListPanelActions *_listPanelActions; TabActions *_tabActions; QPointer sysTray; bool isStarting; QTimer _openUrlTimer; QString _urlToOpen; bool _quit; }; // main modules #define krApp Krusader::App #ifdef __KJSEMBED__ #define krJS Krusader::App->js #endif #endif diff --git a/krusader/panelmanager.h b/krusader/panelmanager.h index 94cabe9b..f42d0220 100644 --- a/krusader/panelmanager.h +++ b/krusader/panelmanager.h @@ -1,149 +1,149 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 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 PANELMANAGER_H #define PANELMANAGER_H #include "abstractpanelmanager.h" // QtWidgets #include #include #include #include #include #include "paneltabbar.h" class QStackedWidget; class QToolButton; class ListPanel; class KrMainWindow; class TabActions; /** * Implements tabbed-browsing by managing a list of tabs and corresponding panels. */ class PanelManager: public QWidget, public AbstractPanelManager { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.krusader.PanelManager") public: /** * PanelManager is created where once panels were created. It accepts three references to pointers * (self, other, active), which enables it to manage pointers held by the panels transparently. * It also receives a bool (left) which is true if the manager is the left one, or false otherwise. */ PanelManager(QWidget *parent, KrMainWindow* mainWindow, bool left); void saveSettings(KConfigGroup config, bool saveHistory); void loadSettings(KConfigGroup config); int findTab(QUrl url); int tabCount() { return _tabbar->count(); } int activeTab(); void setActiveTab(int index); void moveTabToOtherSide(); void moveTabToLeft(); void moveTabToRight(); /** Refresh all tabs after config changes. */ void reloadConfig(); void layoutTabs(); void setLeft(bool left) { _left = left; } void setOtherManager(PanelManager *other) { _otherManager = other; } // AbstractPanelManager implementation - bool isLeft() const Q_DECL_OVERRIDE { return _left; } - AbstractPanelManager *otherManager() const Q_DECL_OVERRIDE { return _otherManager; } - KrPanel *currentPanel() const Q_DECL_OVERRIDE; - void newTab(const QUrl &url, KrPanel *nextTo) Q_DECL_OVERRIDE { + bool isLeft() const override { return _left; } + AbstractPanelManager *otherManager() const override { return _otherManager; } + KrPanel *currentPanel() const override; + void newTab(const QUrl &url, KrPanel *nextTo) override { slotNewTab(url, true, nextTo); } signals: void draggingTab(PanelManager *from, QMouseEvent*); void draggingTabFinished(PanelManager *from, QMouseEvent*); void setActiveManager(PanelManager *manager); void pathChanged(ListPanel *panel); public slots: /** * Called externally to start a new tab. Example of usage would be the "open in a new tab" * action, from the context-menu. */ Q_SCRIPTABLE void newTab(const QString& url) { slotNewTab(QUrl::fromUserInput(url, QString(), QUrl::AssumeLocalFile)); } Q_SCRIPTABLE void newTabs(const QStringList& urls); void slotNewTab(const QUrl &url, bool setCurrent = true, KrPanel *nextTo = nullptr); void slotNewTab(); void slotLockTab(); void slotPinTab(); void slotNextTab(); void slotPreviousTab(); void slotCloseTab(); void slotCloseTab(int index); void slotRecreatePanels(); void slotCloseInactiveTabs(); void slotCloseDuplicatedTabs(); protected slots: void slotCurrentTabChanged(int index); void activate(); void slotDraggingTab(QMouseEvent *e) { emit draggingTab(this, e); } void slotDraggingTabFinished(QMouseEvent* e) { emit draggingTabFinished(this, e); } private: void deletePanel(ListPanel *p); void updateTabbarPos(); void tabsCountChanged(); ListPanel* addPanel(bool setCurrent = true, const KConfigGroup& cfg = KConfigGroup(), KrPanel *nextTo = nullptr); ListPanel* createPanel(const KConfigGroup& cfg); void connectPanel(ListPanel *p); void disconnectPanel(ListPanel *p); PanelManager *_otherManager; TabActions *_actions; QGridLayout *_layout; QHBoxLayout *_barLayout; bool _left; PanelTabBar *_tabbar; QStackedWidget *_stack; QToolButton *_newTab; ListPanel *_currentPanel; }; #endif // _PANEL_MANAGER_H diff --git a/krusader/paneltabbar.h b/krusader/paneltabbar.h index c400e111..093b2f06 100644 --- a/krusader/paneltabbar.h +++ b/krusader/paneltabbar.h @@ -1,117 +1,117 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * Copyright (C) 2004-2019 Krusader Krew [https://krusader.org] * * * * Based on original code from Sebastian Trueg * * * * 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 PANELTABBAR_H #define PANELTABBAR_H // QtCore #include #include // QtGui #include #include // QtWidgets #include class QMouseEvent; class QAction; class KActionMenu; class KrPanel; class ListPanel; class TabActions; /** * This class extends QTabBar such that right-clicking on a tab pops-up a menu * containing relevant actions for the tab. It also emits signals (caught by PanelManager) * to create a new tab, close the current tab and change a panel when a tab was clicked */ class PanelTabBar : public QTabBar { Q_OBJECT public: PanelTabBar(QWidget *parent, TabActions *actions); public slots: /** * called by PanelManager with an already created panel, and creates the corresponding tab */ int addPanel(ListPanel *panel, bool setCurrent = true, KrPanel *nextTo = nullptr); ListPanel* getPanel(int tabIdx); void changePanel(int tabIdx, ListPanel *panel); void layoutTabs(); /** * when the user changes the current path in a panel, this method updates the tab accordingly */ void updateTab(ListPanel *panel); /** * actually removes the current tab WITHOUT actually deleting the panel. * returns a pointer to the panel which is going to be displayed next. * panelToDelete returns a reference to the pointer of the soon-to-die panel, to * be used by PanelManager. */ ListPanel* removeCurrentPanel(ListPanel* &panelToDelete); // returns the panel focused after removing the current ListPanel* removePanel(int index, ListPanel* &panelToDelete); signals: /** * emitted when the user right-clicks and selected "close" */ void closeCurrentTab(); /** * emitted when the user right-clicks and selects an action that creates a new tab */ void newTab(const QUrl &path); void draggingTab(QMouseEvent*); void draggingTabFinished(QMouseEvent*); protected: - void mouseMoveEvent(QMouseEvent*e) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent*) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent*) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent*e) override; + void mousePressEvent(QMouseEvent*) override; + void mouseReleaseEvent(QMouseEvent*) override; void insertAction(QAction*); QString squeeze(const QUrl &url, int tabIndex = -1); - void dragEnterEvent(QDragEnterEvent *) Q_DECL_OVERRIDE; - void dragLeaveEvent(QDragLeaveEvent *) Q_DECL_OVERRIDE; - void dragMoveEvent(QDragMoveEvent *) Q_DECL_OVERRIDE; - void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; + void dragEnterEvent(QDragEnterEvent *) override; + void dragLeaveEvent(QDragLeaveEvent *) override; + void dragMoveEvent(QDragMoveEvent *) override; + void resizeEvent(QResizeEvent *e) override; protected slots: void duplicateTab(); private: void setIcon(int index, ListPanel *panel); void handleDragEvent(int tabIndex); void setPanelTextToTab(int tabIndex, ListPanel *panel); KActionMenu *_panelActionMenu; bool _left; int _maxTabLength; bool _tabClicked, _draggingTab; QTimer *_dragTimer; int _dragTabIndex; }; #endif