diff --git a/krArc/krarc.cpp b/krArc/krarc.cpp index 55471e13..961ad415 100644 --- a/krArc/krarc.cpp +++ b/krArc/krarc.cpp @@ -1,1930 +1,1934 @@ -/*************************************************************************** - krarc.cpp - ------------------- - begin : Sat Jun 14 14:42:49 IDT 2003 - copyright : (C) 2003 by Rafi Yanai & Shie Erlich - email : krusader@users.sf.net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "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 #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) {} virtual ~KrArcCodec() {} virtual QByteArray name() const { return originalCodec->name(); } virtual QList aliases() const { return originalCodec->aliases(); } virtual int mibEnum() const { return originalCodec->mibEnum(); } protected: virtual QString convertToUnicode(const char *in, int length, ConverterState *state) const { return originalCodec->toUnicode(in, length, state); } virtual QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const { // 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); } #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(0L), extArcReady(false), password(QString()), krConf("krusaderrc"), codec(0) { 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; 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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_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, SIGNAL(newOutputData(KProcess *, QByteArray &)), this, SLOT(receivedData(KProcess *, QByteArray &))); 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_COULD_NOT_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_COULD_NOT_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_COULD_NOT_WRITE, getPath(dest, QUrl::StripTrailingSlash) + "\n\n" + proc.getErrorMsg()); return; } if (!QFileInfo(getPath(dest, QUrl::StripTrailingSlash)).exists()) { error(KIO::ERR_COULD_NOT_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().replace(arcPath + '/', "") << dest.path().replace(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(0); 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 == 0) 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 = 0L; } 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 == 0) 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 erronously 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_COULD_NOT_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 UDSEntryList* root = new UDSEntryList(); dirDict.insert(DIR_SEPARATOR, root); // and the "/" UDSEntry UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_NAME, "."); mode_t mode = parsePermString("drwxr-xr-x"); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only 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 0; QHash::iterator itef = dirDict.find(arcDir); if (itef == dirDict.end()) return 0; 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 0; } 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_WS_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_WS_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(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.insert(KIO::UDSEntry::UDS_NAME, name); mode_t mode = parsePermString("drwxr-xr-x"); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only entry.insert(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only entry.insert(KIO::UDSEntry::UDS_SIZE, 0); 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(0); 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(0, 8); // Owner & Group owner = nextWord(line); group = nextWord(line); // symlink destination #ifndef Q_WS_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.insert(KIO::UDSEntry::UDS_NAME, name); // file type entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, mode & S_IFMT); // keep file type only // file permissions entry.insert(KIO::UDSEntry::UDS_ACCESS, mode & 07777); // keep permissions only // file size entry.insert(KIO::UDSEntry::UDS_SIZE, size); // modification time entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, time); // link destination if (!symlinkDest.isEmpty()) { 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->insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, time); entryIt->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_WS_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, SIGNAL(newOutputData(KProcess *, QByteArray &)), this, SLOT(checkOutputForPassword(KProcess *, QByteArray &))); 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 (QStringList::Iterator it = path.begin(); it != path.end(); ++it) { 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(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(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_WS_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 919c284b..8dbadf2f 100644 --- a/krArc/krarc.h +++ b/krArc/krarc.h @@ -1,141 +1,145 @@ -/*************************************************************************** - krarc.h - ------------------- - begin : Sat Jun 14 14:42:49 IDT 2003 - copyright : (C) 2003 by Rafi Yanai & Shie Erlich - email : yanai@users.sf.net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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); virtual ~kio_krarcProtocol(); virtual void stat(const QUrl &url) Q_DECL_OVERRIDE; virtual void get(const QUrl &url) Q_DECL_OVERRIDE; virtual void put(const QUrl &url, int permissions, KIO::JobFlags flags) Q_DECL_OVERRIDE; virtual void mkdir(const QUrl &url, int permissions) Q_DECL_OVERRIDE; virtual void listDir(const QUrl &url) Q_DECL_OVERRIDE; virtual void del(QUrl const & url, bool isFile) Q_DECL_OVERRIDE; virtual void copy(const QUrl &src, const QUrl &dest, int permissions, KIO::JobFlags flags) Q_DECL_OVERRIDE; virtual void rename(const QUrl &src, const QUrl & dest, KIO::JobFlags flags) Q_DECL_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); 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 = 0); QString localeEncodedString(QString str); QByteArray encodeString(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 permittion 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(QString path); QString fullPathName(QString name); static QString detectFullPathName(QString name); bool checkWriteSupport(); QHash dirDict; //< the directoris 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_WS_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/krArc/krarcbasemanager.cpp b/krArc/krarcbasemanager.cpp index 9f8280a1..21a27aaa 100644 --- a/krArc/krarcbasemanager.cpp +++ b/krArc/krarcbasemanager.cpp @@ -1,230 +1,234 @@ -/*************************************************************************** - krarcbasemanager.cpp - -------------------- - copyright : (C) 2003 by Rafi Yanai & Shie Erlich - email : krusader@users.sf.net - web site : http://krusader.sourceforge.net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krarcbasemanager.h" #include KrArcBaseManager::AutoDetectParams KrArcBaseManager::autoDetectParams[] = {{"zip", 0, "PK\x03\x04"}, {"rar", 0, "Rar!\x1a" }, {"arj", 0, "\x60\xea" }, {"rpm", 0, "\xed\xab\xee\xdb"}, {"ace", 7, "**ACE**" }, {"bzip2", 0, "\x42\x5a\x68\x39\x31" }, {"gzip", 0, "\x1f\x8b"}, {"deb", 0, "!\ndebian-binary " }, {"7z", 0, "7z\xbc\xaf\x27\x1c" }/*, {"xz", 0, "\xfd\x37\x7a\x58\x5a\x00"}*/ }; int KrArcBaseManager::autoDetectElems = sizeof(autoDetectParams) / sizeof(AutoDetectParams); const int KrArcBaseManager::maxLenType = 5; //! Checks if a returned status ("exit code") of an archiving-related process is OK /*! \param arcType A short QString which contains an identifier of the type of the archive. \param exitCode The returned status ("exit code") of an archiving-related process. \return If the exit code means that the archiving-related process ended without errors. */ bool KrArcBaseManager::checkStatus(const QString &arcType, int exitCode) { if (arcType == "zip" || arcType == "rar" || arcType == "7z") return exitCode == 0 || exitCode == 1; else if (arcType == "ace" || arcType == "bzip2" || arcType == "lha" || arcType == "rpm" || arcType == "cpio" || arcType == "tar" || arcType == "tarz" || arcType == "tbz" || arcType == "tgz" || arcType == "arj" || arcType == "deb" || arcType == "tlz" || arcType == "txz") return exitCode == 0; else if (arcType == "gzip" || arcType == "lzma" || arcType == "xz") return exitCode == 0 || exitCode == 2; else return exitCode == 0; } QString KrArcBaseManager::detectArchive(bool &encrypted, QString fileName, bool checkEncrypted, bool fast) { encrypted = false; QFile arcFile(fileName); if (arcFile.open(QIODevice::ReadOnly)) { char buffer[ 1024 ]; long sizeMax = arcFile.read(buffer, sizeof(buffer)); arcFile.close(); for (int i = 0; i < autoDetectElems; i++) { QByteArray detectionString = autoDetectParams[ i ].detectionString; int location = autoDetectParams[ i ].location; int endPtr = detectionString.length() + location; if (endPtr > sizeMax) continue; int j = 0; for (; j != detectionString.length(); j++) { if (detectionString[ j ] == '?') continue; if (buffer[ location + j ] != detectionString[ j ]) break; } if (j == detectionString.length()) { QString type = autoDetectParams[ i ].type; if (type == "bzip2" || type == "gzip") { if (fast) { if (fileName.endsWith(QLatin1String(".tar.gz"))) type = "tgz"; else if (fileName.endsWith(QLatin1String(".tar.bz2"))) type = "tbz"; } else { KTar tapeArchive(fileName); if (tapeArchive.open(QIODevice::ReadOnly)) { tapeArchive.close(); if (type == "gzip") type = "tgz"; else if (type == "bzip2") type = "tbz"; } } } else if (type == "zip") encrypted = (buffer[6] & 1); else if (type == "arj") { if (sizeMax > 4) { long headerSize = ((unsigned char *)buffer)[ 2 ] + 256 * ((unsigned char *)buffer)[ 3 ]; long fileHeader = headerSize + 10; if (fileHeader + 9 < sizeMax && buffer[ fileHeader ] == (char)0x60 && buffer[ fileHeader + 1 ] == (char)0xea) encrypted = (buffer[ fileHeader + 8 ] & 1); } } else if (type == "rar") { if (sizeMax > 13 && buffer[ 9 ] == (char)0x73) { if (buffer[ 10 ] & 0x80) { // the header is encrypted? encrypted = true; } else { long offset = 7; long mainHeaderSize = ((unsigned char *)buffer)[ offset+5 ] + 256 * ((unsigned char *)buffer)[ offset+6 ]; offset += mainHeaderSize; while (offset + 10 < sizeMax) { long headerSize = ((unsigned char *)buffer)[ offset+5 ] + 256 * ((unsigned char *)buffer)[ offset+6 ]; bool isDir = (buffer[ offset+7 ] == '\0') && (buffer[ offset+8 ] == '\0') && (buffer[ offset+9 ] == '\0') && (buffer[ offset+10 ] == '\0'); if (buffer[ offset + 2 ] != (char)0x74) break; if (!isDir) { encrypted = (buffer[ offset + 3 ] & 4) != 0; break; } offset += headerSize; } } } } else if (type == "ace") { long offset = 0; long mainHeaderSize = ((unsigned char *)buffer)[ offset+2 ] + 256 * ((unsigned char *)buffer)[ offset+3 ] + 4; offset += mainHeaderSize; while (offset + 10 < sizeMax) { long headerSize = ((unsigned char *)buffer)[ offset+2 ] + 256 * ((unsigned char *)buffer)[ offset+3 ] + 4; bool isDir = (buffer[ offset+11 ] == '\0') && (buffer[ offset+12 ] == '\0') && (buffer[ offset+13 ] == '\0') && (buffer[ offset+14 ] == '\0'); if (buffer[ offset + 4 ] != (char)0x01) break; if (!isDir) { encrypted = (buffer[ offset + 6 ] & 64) != 0; break; } offset += headerSize; } } else if (type == "7z") { // encryption check is expensive, check only if it's necessary if (checkEncrypted) checkIf7zIsEncrypted(encrypted, fileName); } return type; } } if (sizeMax >= 512) { /* checking if it's a tar file */ unsigned checksum = 32 * 8; char chksum[ 9 ]; for (int i = 0; i != 512; i++) checksum += ((unsigned char *)buffer)[ i ]; for (int i = 148; i != 156; i++) checksum -= ((unsigned char *)buffer)[ i ]; sprintf(chksum, "0%o", checksum); if (!memcmp(buffer + 148, chksum, strlen(chksum))) { int k = strlen(chksum); for (; k < 8; k++) if (buffer[148+k] != 0 && buffer[148+k] != 32) break; if (k == 8) return "tar"; } } } if (fileName.endsWith(QLatin1String(".tar.lzma")) || fileName.endsWith(QLatin1String(".tlz"))) { return "tlz"; } if (fileName.endsWith(QLatin1String(".lzma"))) { return "lzma"; } if (fileName.endsWith(QLatin1String(".tar.xz")) || fileName.endsWith(QLatin1String(".txz"))) { return "txz"; } if (fileName.endsWith(QLatin1String(".xz"))) { return "xz"; } return QString(); } //! Returns a short identifier of the type of a file, obtained from the mime type of the file /*! \param mime The mime type of the file. \return A short QString which contains an identifier of the type of the file. */ QString KrArcBaseManager::getShortTypeFromMime(const QString &mime) { // 7zip files are a not a normal case because their mimetype does not // follow the norm of other types: zip, tar, lha, ace, arj, etc. if (mime == "application/x-7z-compressed") return "7z"; // If it's a rar file but its mimetype isn't "application/x-rar" if (mime == "application/x-rar-compressed") return "rar"; // The short type that will be returned QString sType = mime; int lastHyphen = sType.lastIndexOf('-'); if (lastHyphen != -1) sType = sType.mid(lastHyphen + 1); else { int lastSlash = sType.lastIndexOf('/'); if (lastSlash != -1) sType = sType.mid(lastSlash + 1); } // The identifier kept short if (sType.length() > maxLenType) sType = sType.right(maxLenType); return sType; } diff --git a/krArc/krarcbasemanager.h b/krArc/krarcbasemanager.h index 6ddd581c..b5a137f7 100644 --- a/krArc/krarcbasemanager.h +++ b/krArc/krarcbasemanager.h @@ -1,55 +1,59 @@ -/*************************************************************************** - krarcbasemanager.h - ------------------ - copyright : (C) 2003 by Rafi Yanai & Shie Erlich - email : krusader@users.sf.net - web site : http://krusader.sourceforge.net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRARCBASEMANAGER_H #define KRARCBASEMANAGER_H // QtCore #include /*! * \brief An abstract base class for managing archives. */ class KrArcBaseManager { private: //! Information about a type of archive and the bytes that are used to detect it. struct AutoDetectParams { QString type; int location; QByteArray detectionString; }; static AutoDetectParams autoDetectParams[]; //! Information used to detect if a file is an archive static int autoDetectElems; //!< The size of autoDetectParams[] protected: //! The maximum length of a short QString that represents the type of a file static const int maxLenType; static bool checkStatus(const QString &, int); public: KrArcBaseManager() {} QString detectArchive(bool &, QString, bool = true, bool = false); virtual void checkIf7zIsEncrypted(bool &, QString) = 0; static QString getShortTypeFromMime(const QString &); virtual ~KrArcBaseManager() {} }; #endif // KRARCBASEMANAGER_H diff --git a/krArc/krlinecountingprocess.cpp b/krArc/krlinecountingprocess.cpp index 3da69c72..058fb565 100644 --- a/krArc/krlinecountingprocess.cpp +++ b/krArc/krlinecountingprocess.cpp @@ -1,62 +1,66 @@ -/*************************************************************************** - krlinecountingprocess.cpp - ------------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - *************************************************************************** - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krlinecountingprocess.h" KrLinecountingProcess::KrLinecountingProcess() : KProcess() { setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect! connect(this, SIGNAL(readyReadStandardError()), SLOT(receivedError())); connect(this, SIGNAL(readyReadStandardOutput()), SLOT(receivedOutput())); mergedOutput = true; } void KrLinecountingProcess::setMerge(bool value) { mergedOutput = value; } QString KrLinecountingProcess::getErrorMsg() { if (errorData.trimmed().isEmpty()) return QString::fromLocal8Bit(outputData); else return QString::fromLocal8Bit(errorData); } void KrLinecountingProcess::receivedError() { QByteArray newData(this->readAllStandardError()); emit newErrorLines(newData.count('\n')); errorData += newData; if (errorData.length() > 500) errorData = errorData.right(500); if (mergedOutput) receivedOutput(newData); } void KrLinecountingProcess::receivedOutput(QByteArray newData) { if (newData.isEmpty()) newData = this->readAllStandardOutput(); emit newOutputLines(newData.count('\n')); emit newOutputData(this, newData); outputData += newData; if (outputData.length() > 500) outputData = outputData.right(500); } diff --git a/krArc/krlinecountingprocess.h b/krArc/krlinecountingprocess.h index 2acd1ded..43c9a3cc 100644 --- a/krArc/krlinecountingprocess.h +++ b/krArc/krlinecountingprocess.h @@ -1,50 +1,54 @@ -/*************************************************************************** - krlinecountingprocess.h - ----------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - *************************************************************************** - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRLINECOUNTINGPROCESS_H #define KRLINECOUNTINGPROCESS_H #include /** * A KProcess which emits how many lines it is writing to stdout or stderr. */ class KrLinecountingProcess : public KProcess { Q_OBJECT public: KrLinecountingProcess(); void setMerge(bool); QString getErrorMsg(); public slots: void receivedError(); void receivedOutput(QByteArray = QByteArray()); signals: void newOutputLines(int); void newErrorLines(int); void newOutputData(KProcess *, QByteArray &); private: QByteArray errorData; QByteArray outputData; bool mergedOutput; }; #endif // KRLINECOUNTINGPROCESS_H diff --git a/krusader/Archive/abstractthreadedjob.cpp b/krusader/Archive/abstractthreadedjob.cpp index 3fa3096b..f7478598 100644 --- a/krusader/Archive/abstractthreadedjob.cpp +++ b/krusader/Archive/abstractthreadedjob.cpp @@ -1,674 +1,664 @@ -/*************************************************************************** - packjob.cpp - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "abstractthreadedjob.h" // QtCore #include #include #include #include #include #include // QtWidgets #include #include #include #include #include "krarchandler.h" #include "../krglobal.h" #include "../krservices.h" #include "../FileSystem/filesystemprovider.h" extern KRarcHandler arcHandler; AbstractThreadedJob::AbstractThreadedJob() : KIO::Job(), _locker(), _waiter(), _stack(), _maxProgressValue(0), _currentProgress(0), _exiting(false), _jobThread(0) { } void AbstractThreadedJob::startAbstractJobThread(AbstractJobThread * jobThread) { _jobThread = jobThread; _jobThread->setJob(this); _jobThread->moveToThread(_jobThread); _jobThread->start(); } AbstractThreadedJob::~AbstractThreadedJob() { _exiting = true; if (_jobThread) { _jobThread->abort(); _locker.lock(); _waiter.wakeAll(); _locker.unlock(); _jobThread->wait(); delete _jobThread; } } bool AbstractThreadedJob::event(QEvent *e) { if (e->type() == QEvent::User) { UserEvent *event = (UserEvent*) e; switch (event->command()) { case CMD_SUCCESS: { emitResult(); } break; case CMD_ERROR: { int error = event->args()[ 0 ].value(); QString errorText = event->args()[ 1 ].value(); setError(error); setErrorText(errorText); emitResult(); } break; case CMD_INFO: { QString info = event->args()[ 0 ].value(); QString arg1 = event->args()[ 1 ].value(); QString arg2 = event->args()[ 2 ].value(); QString arg3 = event->args()[ 3 ].value(); QString arg4 = event->args()[ 4 ].value(); _title = info; emit description(this, info, qMakePair(arg1, arg2), qMakePair(arg3, arg4)); } break; case CMD_RESET: { QString info = event->args()[ 0 ].value(); QString arg1 = event->args()[ 1 ].value(); QString arg2 = event->args()[ 2 ].value(); QString arg3 = event->args()[ 3 ].value(); QString arg4 = event->args()[ 4 ].value(); _title = info; setProcessedAmount(KJob::Bytes, 0); setTotalAmount(KJob::Bytes, 0); emitSpeed(0); emit description(this, info, qMakePair(arg1, arg2), qMakePair(arg3, arg4)); } break; case CMD_UPLOAD_FILES: case CMD_DOWNLOAD_FILES: { QList sources = KrServices::toUrlList(event->args()[ 0 ].value()); QUrl dest = event->args()[ 1 ].value(); KIO::Job *job = KIO::copy(sources, dest, KIO::HideProgressInfo); addSubjob(job); job->setUiDelegate(new KIO::JobUiDelegate()); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotDownloadResult(KJob*))); connect(job, SIGNAL(processedAmount(KJob*,KJob::Unit,qulonglong)), this, SLOT(slotProcessedAmount(KJob*,KJob::Unit,qulonglong))); connect(job, SIGNAL(totalAmount(KJob*,KJob::Unit,qulonglong)), this, SLOT(slotTotalAmount(KJob*,KJob::Unit,qulonglong))); connect(job, SIGNAL(speed(KJob*,ulong)), this, SLOT(slotSpeed(KJob*,ulong))); connect(job, SIGNAL(description(KJob*,QString,QPair,QPair)), this, SLOT(slotDescription(KJob*,QString,QPair,QPair))); } break; case CMD_MAXPROGRESSVALUE: { qulonglong maxValue = event->args()[ 0 ].value(); _maxProgressValue = maxValue; _currentProgress = 0; } break; case CMD_ADD_PROGRESS: { qulonglong progress = event->args()[ 0 ].value(); _currentProgress += progress; if (_maxProgressValue != 0) { setPercent(100 * _currentProgress / _maxProgressValue); int elapsed = _time.isNull() ? 1 : _time.secsTo(QTime::currentTime()); if (elapsed != 0 && event->args().count() > 1) { _time = QTime::currentTime(); QString progressString = (event->args()[ 1 ].value()); emit description(this, _title, qMakePair(progressString, QString("%1/%2").arg(_currentProgress).arg(_maxProgressValue)), qMakePair(QString(), QString()) ); } } } break; case CMD_GET_PASSWORD: { QString path = event->args()[ 0 ].value(); QString password = KRarcHandler::getPassword(path); QList *resultResp = new QList (); (*resultResp) << password; addEventResponse(resultResp); } break; case CMD_MESSAGE: { QString message = event->args()[ 0 ].value(); KIO::JobUiDelegate *ui = static_cast(uiDelegate()); KMessageBox::information(ui ? ui->window() : 0, message); QList *resultResp = new QList (); addEventResponse(resultResp); } break; } return true; } else { return KIO::Job::event(e); } } void AbstractThreadedJob::addEventResponse(QList * obj) { _locker.lock(); _stack.push(obj); _waiter.wakeOne(); _locker.unlock(); } QList * AbstractThreadedJob::getEventResponse(UserEvent * event) { _locker.lock(); QApplication::postEvent(this, event); _waiter.wait(&_locker); if (_exiting) return 0; QList *resp = _stack.pop(); _locker.unlock(); return resp; } void AbstractThreadedJob::sendEvent(UserEvent * event) { QApplication::postEvent(this, event); } void AbstractThreadedJob::slotDownloadResult(KJob* job) { QList *resultResp = new QList (); if (job) { (*resultResp) << QVariant(job->error()); (*resultResp) << QVariant(job->errorText()); } else { (*resultResp) << QVariant(KJob::UserDefinedError); (*resultResp) << QVariant(QString(i18n("Internal error, undefined in result signal"))); } addEventResponse(resultResp); } void AbstractThreadedJob::slotProcessedAmount(KJob *, KJob::Unit unit, qulonglong xu) { setProcessedAmount(unit, xu); } void AbstractThreadedJob::slotTotalAmount(KJob *, KJob::Unit unit, qulonglong xu) { setTotalAmount(unit, xu); } void AbstractThreadedJob::slotSpeed(KJob *, unsigned long spd) { emitSpeed(spd); } void AbstractThreadedJob::slotDescription(KJob *, const QString &title, const QPair &field1, const QPair &field2) { QString mytitle = title; if (!_title.isNull()) mytitle = _title; emit description(this, mytitle, field1, field2); } class AbstractJobObserver : public KRarcObserver { protected: AbstractJobThread * _jobThread; public: explicit AbstractJobObserver(AbstractJobThread * thread): _jobThread(thread) {} virtual ~AbstractJobObserver() {} virtual void processEvents() Q_DECL_OVERRIDE { usleep(1000); qApp->processEvents(); } virtual void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE { _jobThread->sendReset(jobTitle); _jobThread->sendMaxProgressValue(count); } virtual void subJobStopped() Q_DECL_OVERRIDE { } virtual bool wasCancelled() Q_DECL_OVERRIDE { return _jobThread->_exited; } virtual void error(const QString & error) Q_DECL_OVERRIDE { _jobThread->sendError(KIO::ERR_NO_CONTENT, error); } virtual void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE { _jobThread->sendError(KIO::ERR_NO_CONTENT, error + '\n' + details); } virtual void incrementProgress(int c) Q_DECL_OVERRIDE { _jobThread->sendAddProgress(c, _jobThread->_progressTitle); } }; AbstractJobThread::AbstractJobThread() : _job(0), _downloadTempDir(0), _observer(0), _tempFile(0), _tempDir(0), _exited(false) { } AbstractJobThread::~AbstractJobThread() { if (_downloadTempDir) { delete _downloadTempDir; _downloadTempDir = 0; } if (_observer) { delete _observer; _observer = 0; } if (_tempFile) { delete _tempFile; _tempFile = 0; } } void AbstractJobThread::run() { QTimer::singleShot(0, this, SLOT(slotStart())); QPointer threadLoop = new QEventLoop(this); _loop = threadLoop; threadLoop->exec(); _loop = 0; delete threadLoop; } void AbstractJobThread::terminate() { if (_loop && !_exited) { _loop->quit(); _exited = true; } } void AbstractJobThread::abort() { terminate(); } QList AbstractJobThread::remoteUrls(const QUrl &baseUrl, const QStringList & files) { QList urlList; foreach(const QString &name, files) { QUrl url = baseUrl; url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (name)); urlList << url; } return urlList; } QUrl AbstractJobThread::downloadIfRemote(const QUrl &baseUrl, const QStringList & files) { // download remote URL-s if necessary if (!baseUrl.isLocalFile()) { sendInfo(i18n("Downloading remote files")); _downloadTempDir = new QTemporaryDir(); QList urlList = remoteUrls(baseUrl, files); QUrl dest(_downloadTempDir->path()); QList args; args << KrServices::toStringList(urlList); args << dest; UserEvent * downloadEvent = new UserEvent(CMD_DOWNLOAD_FILES, args); QList * result = _job->getEventResponse(downloadEvent); if (result == 0) return QUrl(); int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return QUrl(); } else { return dest; } } else { return baseUrl; } } QString AbstractJobThread::tempFileIfRemote(const QUrl &kurl, const QString &type) { if (kurl.isLocalFile()) { return kurl.path(); } _tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.") + type); _tempFile->open(); _tempFileName = _tempFile->fileName(); _tempFile->close(); // necessary to create the filename QFile::remove(_tempFileName); _tempFileTarget = kurl; return _tempFileName; } QString AbstractJobThread::tempDirIfRemote(const QUrl &kurl) { if (kurl.isLocalFile()) { return kurl.adjusted(QUrl::StripTrailingSlash).path(); } _tempDir = new QTemporaryDir(); _tempDirTarget = kurl; return _tempDirName = _tempDir->path(); } void AbstractJobThread::sendSuccess() { terminate(); QList args; UserEvent * errorEvent = new UserEvent(CMD_SUCCESS, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendError(int errorCode, QString message) { terminate(); QList args; args << errorCode; args << message; UserEvent * errorEvent = new UserEvent(CMD_ERROR, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendInfo(QString message, QString a1, QString a2, QString a3, QString a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; UserEvent * infoEvent = new UserEvent(CMD_INFO, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendReset(QString message, QString a1, QString a2, QString a3, QString a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; UserEvent * infoEvent = new UserEvent(CMD_RESET, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendMaxProgressValue(qulonglong value) { QList args; args << value; UserEvent * infoEvent = new UserEvent(CMD_MAXPROGRESSVALUE, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendAddProgress(qulonglong value, const QString &progress) { QList args; args << value; if (!progress.isNull()) args << progress; UserEvent * infoEvent = new UserEvent(CMD_ADD_PROGRESS, args); _job->sendEvent(infoEvent); } void countFiles(const QString &path, unsigned long &totalFiles, bool &stop) { const QDir dir(path); if (!dir.exists()) { totalFiles++; // assume its a file return; } for (const QString name : dir.entryList()) { if (stop) return; if (name == QStringLiteral(".") || name == QStringLiteral("..")) continue; countFiles(dir.absoluteFilePath(name), totalFiles, stop); } } void AbstractJobThread::countLocalFiles(const QUrl &baseUrl, const QStringList &names, unsigned long &totalFiles) { sendReset(i18n("Counting files")); FileSystem *calcSpaceFileSystem = FileSystemProvider::instance().getFilesystem(baseUrl); calcSpaceFileSystem->scanDir(baseUrl); for (const QString name : names) { if (_exited) return; const QString path = calcSpaceFileSystem->getUrl(name).toLocalFile(); if (!QFileInfo(path).exists()) return; countFiles(path, totalFiles, _exited); } delete calcSpaceFileSystem; } KRarcObserver * AbstractJobThread::observer() { if (_observer) return _observer; _observer = new AbstractJobObserver(this); return _observer; } bool AbstractJobThread::uploadTempFiles() { if (_tempFile != 0 || _tempDir != 0) { sendInfo(i18n("Uploading to remote destination")); if (_tempFile) { QList urlList; urlList << QUrl::fromLocalFile(_tempFileName); QList args; args << KrServices::toStringList(urlList); args << _tempFileTarget; UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == 0) return false; int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return false; } } if (_tempDir) { QList urlList; QDir tempDir(_tempDirName); QStringList list = tempDir.entryList(); foreach(const QString &name, list) { if (name == "." || name == "..") continue; QUrl url = QUrl::fromLocalFile(_tempDirName).adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (name)); urlList << url; } QList args; args << KrServices::toStringList(urlList); args << _tempDirTarget; UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == 0) return false; int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return false; } } } return true; } QString AbstractJobThread::getPassword(const QString &path) { QList args; args << path; UserEvent * getPasswdEvent = new UserEvent(CMD_GET_PASSWORD, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == 0) return QString(); QString password = (*result)[ 0 ].value(); if (password.isNull()) password = QString(""); delete result; return password; } void AbstractJobThread::sendMessage(const QString &message) { QList args; args << message; UserEvent * getPasswdEvent = new UserEvent(CMD_MESSAGE, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == 0) return; delete result; } //! Gets some archive information that is needed in several cases. /*! \param path A path to the archive. \param type The type of the archive. \param password The password of the archive. \param arcName The name of the archive. \param sourceFolder A QUrl, which may be remote, of the folder where the archive is. \return If the archive information has been obtained. */ bool AbstractJobThread::getArchiveInformation(QString &path, QString &type, QString &password, QString &arcName, const QUrl &sourceFolder) { // Safety checks (though the user shouldn't have been able to select something named "" or "..") if (arcName.isEmpty()) return false; if (arcName == "..") return false; QUrl url = sourceFolder.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + arcName); path = url.adjusted(QUrl::StripTrailingSlash).path(); QMimeDatabase db; QMimeType mt = db.mimeTypeForUrl(url); QString mime = mt.isValid() ? mt.name() : QString(); bool encrypted = false; type = arcHandler.getType(encrypted, path, mime); // Check that the archive is supported if (!KRarcHandler::arcSupported(type)) { sendError(KIO::ERR_NO_CONTENT, i18nc("%1=archive filename", "%1, unsupported archive type.", arcName)); return false; } password = encrypted ? getPassword(path) : QString(); return true; } diff --git a/krusader/Archive/abstractthreadedjob.h b/krusader/Archive/abstractthreadedjob.h index 6f8f7ad4..4ea06ad0 100644 --- a/krusader/Archive/abstractthreadedjob.h +++ b/krusader/Archive/abstractthreadedjob.h @@ -1,198 +1,188 @@ -/*************************************************************************** - threadedjob.h - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef 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 void startAbstractJobThread(AbstractJobThread*); virtual bool doSuspend() Q_DECL_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; 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, QString message); void sendInfo(QString message, QString a1 = QString(), QString a2 = QString(), QString a3 = QString(), QString a4 = QString()); void sendReset(QString message, QString a1 = QString(""), QString a2 = QString(""), QString a3 = QString(""), 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.cpp b/krusader/Archive/kr7zencryptionchecker.cpp index 731a0bb1..222d2e81 100644 --- a/krusader/Archive/kr7zencryptionchecker.cpp +++ b/krusader/Archive/kr7zencryptionchecker.cpp @@ -1,59 +1,63 @@ -/*************************************************************************** - kr7zencryptionchecker.cpp - ------------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - *************************************************************************** - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kr7zencryptionchecker.h" Kr7zEncryptionChecker::Kr7zEncryptionChecker() : KProcess(), encrypted(false), lastData() { setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect! connect(this, SIGNAL(readyReadStandardOutput()), SLOT(receivedOutput())); } void Kr7zEncryptionChecker::setupChildProcess() { // This function is called after the fork but for the exec. We create a process group // to work around a broken wrapper script of 7z. Without this only the wrapper is killed. setsid(); // make this process leader of a new process group } void Kr7zEncryptionChecker::receivedOutput() { QString data = QString::fromLocal8Bit(this->readAllStandardOutput()); 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")) { encrypted = true; ::kill(- pid(), SIGKILL); // kill the whole process group by giving the negative PID } } } bool Kr7zEncryptionChecker::isEncrypted() { return encrypted; } diff --git a/krusader/Archive/kr7zencryptionchecker.h b/krusader/Archive/kr7zencryptionchecker.h index 4278206c..ae48553b 100644 --- a/krusader/Archive/kr7zencryptionchecker.h +++ b/krusader/Archive/kr7zencryptionchecker.h @@ -1,49 +1,53 @@ -/*************************************************************************** - kr7zencryptionchecker.h - ----------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - *************************************************************************** - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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: virtual void setupChildProcess() Q_DECL_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 3764d108..abc292f1 100644 --- a/krusader/Archive/krarchandler.cpp +++ b/krusader/Archive/krarchandler.cpp @@ -1,681 +1,672 @@ -/*************************************************************************** - krarchandler.cpp - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krarchandler.h" // QtCore #include #include #include // QtWidgets #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 { usleep(1000); qApp->processEvents(); } virtual void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE { krApp->startWaiting(jobTitle, count, true); } virtual void subJobStopped() Q_DECL_OVERRIDE { krApp->stopWait(); } virtual bool wasCancelled() Q_DECL_OVERRIDE { return krApp->wasWaitingCancelled(); } virtual void error(const QString & error) Q_DECL_OVERRIDE { KMessageBox::error(krApp, error, i18n("Error")); } virtual void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE { KMessageBox::detailedError(krApp, error, details, i18n("Error")); } virtual void incrementProgress(int c) Q_DECL_OVERRIDE { krApp->plzWait->incProgress(c); } }; #endif static QStringList arcProtocols = QString("tar;bzip;bzip2;lzma;xz;gzip;krarc;zip").split(';'); KWallet::Wallet * KRarcHandler::wallet = 0; 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(QString archive, QString type, 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, QString type, QString password, 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, SIGNAL(newOutputLines(int)), observer, SLOT(incrementProgress(int))); if (type == "rpm") connect(&proc, SIGNAL(newErrorLines(int)), observer, SLOT(incrementProgress(int))); } // 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(QString archive, QString type, 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, SIGNAL(newOutputLines(int)), observer, SLOT(incrementProgress(int))); // 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, 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 (QStringList::Iterator file = fileNames.begin(); file != fileNames.end(); ++file) { proc << *file; } // tell the user to wait observer->subJobStarted(i18n("Packing File(s)"), count); if (count != 0) connect(&proc, SIGNAL(newOutputLines(int)), observer, SLOT(incrementProgress(int))); // 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 != 0); } QString KRarcHandler::getPassword(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 != 0) { delete wallet; wallet = 0; } 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(0L, 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 != 0) { delete wallet; wallet = 0; } 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, QString mime, bool checkEncrypted, bool fast) { QString result = detectArchive(encrypted, fileName, checkEncrypted, fast); if (result.isNull()) { // Then the type is based on the mime type return getShortTypeFromMime(mime); } return result; } bool KRarcHandler::checkStatus(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 cd637f13..12977563 100644 --- a/krusader/Archive/krarchandler.h +++ b/krusader/Archive/krarchandler.h @@ -1,96 +1,87 @@ -/*************************************************************************** - krarchandler.h - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description: this class will supply static archive handling functions. - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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: virtual ~KRarcObserver() {} 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(QString archive, QString type, QString password, KRarcObserver *observer); // unpack an archive to destination directory static bool unpack(QString archive, QString type, QString password, QString dest, KRarcObserver *observer ); // pack an archive to destination directory static bool pack(QStringList fileNames, QString type, QString dest, long count, QMap extraProps, KRarcObserver *observer ); // test an archive static bool test(QString archive, QString type, 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, QString mime, bool checkEncrypted = true, bool fast = false); // queries the password from the user static QString getPassword(QString path); // detects the archive type void checkIf7zIsEncrypted(bool &, QString); private: //! checks if a returned status ("exit code") of an archiving-related process is OK static bool checkStatus(QString type, int exitCode); static bool openWallet(); static KWallet::Wallet * wallet; }; #endif diff --git a/krusader/Archive/packjob.cpp b/krusader/Archive/packjob.cpp index 8b1b8db6..8409238e 100644 --- a/krusader/Archive/packjob.cpp +++ b/krusader/Archive/packjob.cpp @@ -1,179 +1,169 @@ -/*************************************************************************** - packjob.cpp - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "packjob.h" #include "krarchandler.h" // QtCore #include #include #include #include #include extern KRarcHandler arcHandler; PackJob::PackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps) : AbstractThreadedJob() { startAbstractJobThread(new PackThread(srcUrl, destUrl, fileNames, type, packProps)); } PackJob * PackJob::createPacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps) { return new PackJob(srcUrl, destUrl, fileNames, type, packProps); } PackThread::PackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps) : AbstractJobThread(), _sourceUrl(srcUrl), _destUrl(destUrl), _fileNames(fileNames), _type(type), _packProperties(packProps) { } void PackThread::slotStart() { QUrl newSource = downloadIfRemote(_sourceUrl, _fileNames); if (newSource.isEmpty()) return; unsigned long totalFiles = 0; countLocalFiles(newSource, _fileNames, totalFiles); QString arcFile = tempFileIfRemote(_destUrl, _type); QString arcDir = newSource.adjusted(QUrl::StripTrailingSlash).path(); setProgressTitle(i18n("Processed files")); QString save = QDir::currentPath(); QDir::setCurrent(arcDir); bool result = KRarcHandler::pack(_fileNames, _type, arcFile, totalFiles, _packProperties, observer()); QDir::setCurrent(save); if (isExited()) return; if (!result) { sendError(KIO::ERR_INTERNAL, i18n("Error while packing")); return; } if (!uploadTempFiles()) return; sendSuccess(); } TestArchiveJob::TestArchiveJob(const QUrl &srcUrl, const QStringList & fileNames) : AbstractThreadedJob() { startAbstractJobThread(new TestArchiveThread(srcUrl, fileNames)); } TestArchiveJob * TestArchiveJob::testArchives(const QUrl &srcUrl, const QStringList & fileNames) { return new TestArchiveJob(srcUrl, fileNames); } TestArchiveThread::TestArchiveThread(const QUrl &srcUrl, const QStringList & fileNames) : AbstractJobThread(), _sourceUrl(srcUrl), _fileNames(fileNames) { } void TestArchiveThread::slotStart() { // Gets a QUrl of the source folder, which may be remote QUrl newSource = downloadIfRemote(_sourceUrl, _fileNames); if (newSource.isEmpty()) return; for (int i = 0; i < _fileNames.count(); ++i) { QString path, type, password, arcName = _fileNames[i]; if (!getArchiveInformation(path, type, password, arcName, newSource)) return; // test the archive if (!KRarcHandler::test(path, type, password, observer(), 0)) { sendError(KIO::ERR_NO_CONTENT, i18nc("%1=archive filename", "%1, test failed.", arcName)); return; } } sendMessage(i18n("Archive tests passed.")); sendSuccess(); } UnpackJob::UnpackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames) : AbstractThreadedJob() { startAbstractJobThread(new UnpackThread(srcUrl, destUrl, fileNames)); } UnpackJob * UnpackJob::createUnpacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames) { return new UnpackJob(srcUrl, destUrl, fileNames); } UnpackThread::UnpackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames) : AbstractJobThread(), _sourceUrl(srcUrl), _destUrl(destUrl), _fileNames(fileNames) { } void UnpackThread::slotStart() { // Gets a QUrl of the source folder, which may be remote QUrl newSource = downloadIfRemote(_sourceUrl, _fileNames); if (newSource.isEmpty()) return; QString localDest = tempDirIfRemote(_destUrl); for (int i = 0; i < _fileNames.count(); ++i) { QString path, type, password, arcName = _fileNames[i]; if (!getArchiveInformation(path, type, password, arcName, newSource)) return; setProgressTitle(i18n("Processed files")); // unpack the files bool result = KRarcHandler::unpack(path, type, password, localDest, observer()); if (isExited()) return; if (!result) { sendError(KIO::ERR_INTERNAL, i18n("Error while unpacking")); return; } } if (!uploadTempFiles()) return; sendSuccess(); } diff --git a/krusader/Archive/packjob.h b/krusader/Archive/packjob.h index ff99441e..4d7cab5a 100644 --- a/krusader/Archive/packjob.h +++ b/krusader/Archive/packjob.h @@ -1,135 +1,125 @@ -/*************************************************************************** - packjob.h - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef 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); virtual ~PackThread() {} protected slots: virtual void slotStart() Q_DECL_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); virtual ~TestArchiveThread() {} protected slots: virtual void slotStart() Q_DECL_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); virtual ~UnpackThread() {} protected slots: virtual void slotStart() Q_DECL_OVERRIDE; private: QUrl _sourceUrl; QUrl _destUrl; QStringList _fileNames; }; #endif // __PACK_JOB_H__ diff --git a/krusader/Dialogs/krmaskchoice.cpp b/krusader/Dialogs/krmaskchoice.cpp index c705bf18..89367610 100644 --- a/krusader/Dialogs/krmaskchoice.cpp +++ b/krusader/Dialogs/krmaskchoice.cpp @@ -1,160 +1,151 @@ -/*************************************************************************** - krmaskchoice.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krmaskchoice.h" // QtCore #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include "../GUI/krlistwidget.h" /** * Constructs a KRMaskChoice which is a child of 'parent', with the * name 'name' and widget flags set to 'f' * * The dialog will by default be modeless, unless you set 'modal' to * TRUE to construct a modal dialog. */ KRMaskChoice::KRMaskChoice(QWidget* parent) : QDialog(parent) { setModal(true); resize(401, 314); setWindowTitle(i18n("Choose Files")); QVBoxLayout* MainLayout = new QVBoxLayout(this); QHBoxLayout* HeaderLayout = new QHBoxLayout(); MainLayout->addLayout(HeaderLayout); PixmapLabel1 = new QLabel(this); PixmapLabel1->setScaledContents(true); PixmapLabel1->setMaximumSize(QSize(31, 31)); HeaderLayout->addWidget(PixmapLabel1); label = new QLabel(this); label->setText(i18n("Select the following files:")); HeaderLayout->addWidget(label); selection = new KComboBox(this); selection->setEditable(true); selection->setInsertPolicy(QComboBox::InsertAtTop); selection->setAutoCompletion(true); MainLayout->addWidget(selection); QGroupBox* GroupBox1 = new QGroupBox(this); GroupBox1->setTitle(i18n("Predefined Selections")); MainLayout->addWidget(GroupBox1); QHBoxLayout* gbLayout = new QHBoxLayout(GroupBox1); preSelections = new KrListWidget(GroupBox1); preSelections->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); preSelections->setWhatsThis(i18n("A predefined selection is a file-mask which you often use.\nSome examples are: \"*.c, *.h\", \"*.c, *.o\", etc.\nYou can add these masks to the list by typing them and pressing the Add button.\nDelete removes a predefined selection and Clear removes all of them.\nNotice that the line in which you edit the mask has its own history, you can scroll it, if needed.")); gbLayout->addWidget(preSelections); QVBoxLayout* vbox = new QVBoxLayout(); gbLayout->addLayout(vbox); PushButton7 = new QPushButton(GroupBox1); PushButton7->setText(i18n("Add")); PushButton7->setToolTip(i18n("Adds the selection in the line-edit to the list")); vbox->addWidget(PushButton7); PushButton7_2 = new QPushButton(GroupBox1); PushButton7_2->setText(i18n("Delete")); PushButton7_2->setToolTip(i18n("Delete the marked selection from the list")); vbox->addWidget(PushButton7_2); PushButton7_3 = new QPushButton(GroupBox1); PushButton7_3->setText(i18n("Clear")); PushButton7_3->setToolTip(i18n("Clears the entire list of selections")); vbox->addWidget(PushButton7_3); vbox->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Expanding)); QDialogButtonBox* ButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); MainLayout->addWidget(ButtonBox); // signals and slots connections connect(ButtonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(ButtonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(PushButton7, SIGNAL(clicked()), this, SLOT(addSelection())); connect(PushButton7_2, SIGNAL(clicked()), this, SLOT(deleteSelection())); connect(PushButton7_3, SIGNAL(clicked()), this, SLOT(clearSelections())); connect(selection, SIGNAL(activated(QString)), selection, SLOT(setEditText(QString))); connect(selection->lineEdit(), SIGNAL(returnPressed()), this, SLOT(accept())); connect(preSelections, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(currentItemChanged(QListWidgetItem*))); connect(preSelections, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(acceptFromList(QListWidgetItem*))); } /* * Destroys the object and frees any allocated resources */ KRMaskChoice::~KRMaskChoice() { // no need to delete child widgets, Qt does it all for us } void KRMaskChoice::addSelection() { qWarning("KRMaskChoice::addSelection(): Not implemented yet!"); } void KRMaskChoice::clearSelections() { qWarning("KRMaskChoice::clearSelections(): Not implemented yet!"); } void KRMaskChoice::deleteSelection() { qWarning("KRMaskChoice::deleteSelection(): Not implemented yet!"); } void KRMaskChoice::acceptFromList(QListWidgetItem *) { qWarning("KRMaskChoice::acceptFromList(QListWidgetItem *): Not implemented yet!"); } void KRMaskChoice::currentItemChanged(QListWidgetItem *) { qWarning("KRMaskChoice::currentItemChanged(QListWidgetItem *): Not implemented yet!"); } diff --git a/krusader/Dialogs/krmaskchoice.h b/krusader/Dialogs/krmaskchoice.h index a428dec1..e4a730c1 100644 --- a/krusader/Dialogs/krmaskchoice.h +++ b/krusader/Dialogs/krmaskchoice.h @@ -1,66 +1,57 @@ -/*************************************************************************** - krmaskchoice.h - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRMASKCHOICE_H #define KRMASKCHOICE_H // QtWidgets #include class QLabel; class QListWidgetItem; class QPushButton; class KComboBox; class KrListWidget; class KRMaskChoice : public QDialog { Q_OBJECT public: explicit KRMaskChoice(QWidget* parent = 0); ~KRMaskChoice(); KComboBox* selection; QLabel* PixmapLabel1; QLabel* label; KrListWidget* preSelections; QPushButton* PushButton7; QPushButton* PushButton7_2; QPushButton* PushButton7_3; public slots: virtual void addSelection(); virtual void clearSelections(); virtual void deleteSelection(); virtual void acceptFromList(QListWidgetItem *); virtual void currentItemChanged(QListWidgetItem *); }; #endif // KRMASKCHOICE_H diff --git a/krusader/Dialogs/krpleasewait.cpp b/krusader/Dialogs/krpleasewait.cpp index f3b8741a..a75ec026 100644 --- a/krusader/Dialogs/krpleasewait.cpp +++ b/krusader/Dialogs/krpleasewait.cpp @@ -1,165 +1,156 @@ -/*************************************************************************** - krpleasewait.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krpleasewait.h" // QtCore #include #include // QtGui #include // QtWidgets #include #include #include #include #include #include #include "../krglobal.h" KRPleaseWait::KRPleaseWait(QString msg, QWidget *parent, int count, bool cancel): QProgressDialog(cancel ? 0 : parent) , inc(true) { setModal(!cancel); timer = new QTimer(this); setWindowTitle(i18n("Krusader::Wait")); setMinimumDuration(500); setAutoClose(false); setAutoReset(false); connect(timer, SIGNAL(timeout()), this, SLOT(cycleProgress())); QProgressBar* progress = new QProgressBar(this); progress->setMaximum(count); progress->setMinimum(0); setBar(progress); QLabel* label = new QLabel(this); setLabel(label); QPushButton* btn = new QPushButton(i18n("&Cancel"), this); setCancelButton(btn); btn->setEnabled(canClose = cancel); setLabelText(msg); show(); } void KRPleaseWait::closeEvent(QCloseEvent * e) { if (canClose) { emit canceled(); e->accept(); } else /* if cancel is not allowed, we disable */ e->ignore(); /* the window closing [x] also */ } void KRPleaseWait::incProgress(int howMuch) { setValue(value() + howMuch); } void KRPleaseWait::cycleProgress() { if (inc) setValue(value() + 1); else setValue(value() - 1); if (value() >= 9) inc = false; if (value() <= 0) inc = true; } KRPleaseWaitHandler::KRPleaseWaitHandler(QWidget *parentWindow) : QObject(parentWindow), _parentWindow(parentWindow), job(), dlg(0) { } void KRPleaseWaitHandler::stopWait() { if (dlg != 0) delete dlg; dlg = 0; cycleMutex = incMutex = false; // return cursor to normal arrow _parentWindow->setCursor(Qt::ArrowCursor); } void KRPleaseWaitHandler::startWaiting(QString msg, int count , bool cancel) { if (dlg == 0) { dlg = new KRPleaseWait(msg , _parentWindow, count, cancel); connect(dlg, SIGNAL(canceled()), this, SLOT(killJob())); } incMutex = cycleMutex = _wasCancelled = false; dlg->setValue(0); dlg->setLabelText(msg); if (count == 0) { dlg->setMaximum(10); cycle = true; cycleProgress(); } else { dlg->setMaximum(count); cycle = false; } } void KRPleaseWaitHandler::cycleProgress() { if (cycleMutex) return; cycleMutex = true; if (dlg) dlg->cycleProgress(); if (cycle) QTimer::singleShot(2000, this, SLOT(cycleProgress())); cycleMutex = false; } void KRPleaseWaitHandler::killJob() { if (!job.isNull()) job->kill(KJob::EmitResult); stopWait(); _wasCancelled = true; } void KRPleaseWaitHandler::setJob(KIO::Job* j) { job = j; } void KRPleaseWaitHandler::incProgress(int i) { if (incMutex) return; incMutex = true; if (dlg) dlg->incProgress(i); incMutex = false; } diff --git a/krusader/Dialogs/krpleasewait.h b/krusader/Dialogs/krpleasewait.h index a682d1e7..3d11e2ca 100644 --- a/krusader/Dialogs/krpleasewait.h +++ b/krusader/Dialogs/krpleasewait.h @@ -1,90 +1,81 @@ -/*************************************************************************** - krpleasewait.h - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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(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(QString msg, QWidget *parent, int count = 0 , bool cancel = false); public slots: void incProgress(int howMuch); void cycleProgress(); protected: bool inc; QTimer* timer; virtual void closeEvent(QCloseEvent * e) Q_DECL_OVERRIDE; bool canClose; }; #endif diff --git a/krusader/Dialogs/krspecialwidgets.cpp b/krusader/Dialogs/krspecialwidgets.cpp index 7215dddf..fabe0d6b 100644 --- a/krusader/Dialogs/krspecialwidgets.cpp +++ b/krusader/Dialogs/krspecialwidgets.cpp @@ -1,227 +1,218 @@ -/*************************************************************************** - krspecialwidgets.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krspecialwidgets.h" #include "krmaskchoice.h" #include "newftpgui.h" #include "../krglobal.h" // QtGui #include #include ///////////////////////////////////////////////////////////////////////////// /////////////////////// Pie related widgets ///////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // The pie-related widgets use hard-coded coordinates to create the look. // This is ok since the whole widget is fitted into an existing view and thus // no re-alignments are needed. #define LEFT 10 #define BOTTOM 150 #define WIDTH 120 #define HEIGHT 40 #define Z_HEIGHT 10 #define STARTANGLE 0 #define DEG(x) (16*(x)) QColor KRPie::colors[ 12 ] = {Qt::red, Qt::blue, Qt::green, Qt::cyan, Qt::magenta, Qt::gray, Qt::black, Qt::white, Qt::darkRed, Qt::darkBlue, Qt::darkMagenta, Qt::darkCyan }; ////////////////////////////////////////////////////////////////////////////// /////////////// KRFSDisplay - Filesystem / Freespace Display ///////////////// ////////////////////////////////////////////////////////////////////////////// // This is the full constructor: use it for a mounted filesystem KRFSDisplay::KRFSDisplay(QWidget *parent, QString _alias, QString _realName, KIO::filesize_t _total, KIO::filesize_t _free) : QWidget(parent), totalSpace(_total), freeSpace(_free), alias(_alias), realName(_realName), mounted(true), empty(false), supermount(false) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); resize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); setMinimumSize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); show(); } // Use this one for an unmounted filesystem KRFSDisplay::KRFSDisplay(QWidget *parent, QString _alias, QString _realName, bool sm) : QWidget(parent), alias(_alias), realName(_realName), mounted(false), empty(false), supermount(sm) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); resize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); setMinimumSize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); show(); } // This is used only when an empty widget needs to be displayed (for example: // when filesystem statistics haven't been calculated yet) KRFSDisplay::KRFSDisplay(QWidget *parent) : QWidget(parent), empty(true) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); resize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); setMinimumSize(150 + leftMargin + rightMargin, 200 + topMargin + bottomMargin); show(); } // The main painter! void KRFSDisplay::paintEvent(QPaintEvent *) { QPainter paint(this); if (!empty) { int leftMargin, topMargin, rightMargin, bottomMargin; getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); // create the text // first, name and location QFont font = paint.font(); font.setWeight(QFont::Bold); paint.setFont(font); paint.drawText(leftMargin + 10, topMargin + 20, alias); font.setWeight(QFont::Normal); paint.setFont(font); paint.drawText(leftMargin + 10, topMargin + 37, '(' + realName + ')'); if (mounted) { // incase the filesystem is already mounted // second, the capacity paint.drawText(leftMargin + 10, topMargin + 70, i18n("Capacity: %1", KIO::convertSizeFromKiB(totalSpace))); // third, the 2 boxes (used, free) QPen systemPen = paint.pen(); paint.setPen(Qt::black); paint.drawRect(leftMargin + 10, topMargin + 90, 10, 10); paint.fillRect(leftMargin + 11, topMargin + 91, 8, 8, QBrush(Qt::gray)); paint.drawRect(leftMargin + 10, topMargin + 110, 10, 10); paint.fillRect(leftMargin + 11, topMargin + 111, 8, 8, QBrush(Qt::white)); // now, the text for the boxes paint.setPen(systemPen); paint.drawText(leftMargin + 25, topMargin + 100, i18n("Used: %1", KIO::convertSizeFromKiB(totalSpace - freeSpace))); paint.drawText(leftMargin + 25, topMargin + 120, i18n("Free: %1", KIO::convertSizeFromKiB(freeSpace))); // first, create the empty pie // bottom... paint.setPen(Qt::black); paint.setBrush(Qt::white); paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM, WIDTH, HEIGHT, STARTANGLE, DEG(360)); // body... paint.setPen(Qt::lightGray); for (int i = 1; i < Z_HEIGHT; ++i) paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM - i, WIDTH, HEIGHT, STARTANGLE, DEG(360)); // side lines... paint.setPen(Qt::black); paint.drawLine(leftMargin + LEFT, topMargin + BOTTOM + HEIGHT / 2, LEFT, BOTTOM + HEIGHT / 2 - Z_HEIGHT); paint.drawLine(leftMargin + LEFT + WIDTH, topMargin + BOTTOM + HEIGHT / 2, LEFT + WIDTH, BOTTOM + HEIGHT / 2 - Z_HEIGHT); // top of the pie paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM - Z_HEIGHT, WIDTH, HEIGHT, STARTANGLE, DEG(360)); // the "used space" slice float i = ((float)(totalSpace - freeSpace) / (totalSpace)) * 360.0; paint.setBrush(Qt::gray); paint.drawPie(leftMargin + LEFT, topMargin + BOTTOM - Z_HEIGHT, WIDTH, HEIGHT, STARTANGLE, (int) DEG(i)); // if we need to draw a 3d stripe ... if (i > 180.0) { for (int j = 1; j < Z_HEIGHT; ++j) paint.drawArc(leftMargin + LEFT, topMargin + BOTTOM - j, WIDTH, HEIGHT, STARTANGLE - 16 * 180, (int)(DEG(i - 180.0))); } } else { // if the filesystem is unmounted... font.setWeight(QFont::Bold); paint.setFont(font); paint.drawText(leftMargin + 10, topMargin + 60, i18n("Not mounted.")); } } else { // if the widget is in empty situation... } } //////////////////////////////////////////////////////////////////////////////// KRPie::KRPie(KIO::filesize_t _totalSize, QWidget *parent) : QWidget(parent), totalSize(_totalSize) { slices.push_back(KRPieSlice(100, Qt::yellow, "DEFAULT")); sizeLeft = totalSize; resize(300, 300); } void KRPie::paintEvent(QPaintEvent *) { QPainter paint(this); // now create the slices float sAngle = STARTANGLE; for (int ndx = 0; ndx != slices.count(); ndx++) { paint.setBrush(slices[ndx].getColor()); paint.setPen(slices[ndx].getColor()); // angles are negative to create a clock-wise drawing of slices float angle = -(slices[ndx].getPerct() / 100 * 360) * 16; for (int i = 1; i < Z_HEIGHT; ++i) paint.drawPie(LEFT, BOTTOM + i, WIDTH, HEIGHT, (int) sAngle, (int) angle); sAngle += angle; } paint.setPen(Qt::yellow); // pen paint.setBrush(Qt::yellow); // fill // for (int i=1; i * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRSPECIALWIDGETS_H #define KRSPECIALWIDGETS_H // QtCore #include // QtGui #include #include #include #include // QtWidgets #include #include #include class KRPieSlice; class KRPie : public QWidget { Q_OBJECT public: explicit KRPie(KIO::filesize_t _totalSize, QWidget *parent = 0); void addSlice(KIO::filesize_t size, QString label); protected: void paintEvent(QPaintEvent *); 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 = a; } inline void setRealName(QString r) { realName = 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 *); 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(_color), label(_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 = _label; } private: float perct; QColor color; QString label; }; #endif diff --git a/krusader/Dialogs/krspwidgets.cpp b/krusader/Dialogs/krspwidgets.cpp index d0d5dc1c..8865369b 100644 --- a/krusader/Dialogs/krspwidgets.cpp +++ b/krusader/Dialogs/krspwidgets.cpp @@ -1,269 +1,260 @@ -/*************************************************************************** - krspwidgets.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krspwidgets.h" #include "../krglobal.h" #include "../kicons.h" #include "../Filter/filtertabs.h" #include "../GUI/krlistwidget.h" // QtCore #include // QtGui #include // QtWidgets #include #include #include #include #include #include // missing ? #include #include #include #include #include #include ///////////////////// initiation of the static members //////////////////////// QStringList KRSpWidgets::maskList; /////////////////////////////////////////////////////////////////////////////// KRSpWidgets::KRSpWidgets() { } KRQuery KRSpWidgets::getMask(QString caption, bool nameOnly, QWidget * parent) { if (!nameOnly) { return FilterTabs::getQuery(parent); } else { QPointer p = new KRMaskChoiceSub(parent); p->setWindowTitle(caption); p->exec(); QString selection = p->selection->currentText(); delete p; if (selection.isEmpty()) { return KRQuery(); } else { return KRQuery(selection); } } } /////////////////////////// newFTP //////////////////////////////////////// QUrl KRSpWidgets::newFTP() { QPointer p = new newFTPSub(); p->exec(); QString uri = p->url->currentText(); if (uri.isEmpty()) { delete p; return QUrl(); // empty url } QString protocol = p->prefix->currentText(); protocol.truncate(protocol.length() - 3); // remove the trailing :// QString username = p->username->text().simplified(); QString password = p->password->text().simplified(); int uriStart = uri.lastIndexOf('@'); /* lets the user enter user and password in the URI field */ if (uriStart != -1) { QString uriUser = uri.left(uriStart); QString uriPsw; uri = uri.mid(uriStart + 1); int pswStart = uriUser.indexOf(':'); /* getting the password name from the URL */ if (pswStart != -1) { uriPsw = uriUser.mid(pswStart + 1); uriUser = uriUser.left(pswStart); } if (!uriUser.isEmpty()) { /* handling the ftp proxy username and password also */ username = username.isEmpty() ? uriUser : username + '@' + uriUser; } if (!uriPsw.isEmpty()) { /* handling the ftp proxy username and password also */ password = password.isEmpty() ? uriPsw : password + '@' + uriPsw; } } QString host = uri; /* separating the hostname and path from the uri */ QString path; int pathStart = uri.indexOf("/"); if (pathStart != -1) { path = host.mid(pathStart); host = host.left(pathStart); } /* setting the parameters of the URL */ QUrl url; url.setScheme(protocol); url.setHost(host); url.setPath(path); if (protocol == "ftp" || protocol == "fish" || protocol == "sftp") { url.setPort(p->port->cleanText().toInt()); } if (!username.isEmpty()) { url.setUserName(username); } if (!password.isEmpty()) { url.setPassword(password); } delete p; return url; } newFTPSub::newFTPSub() : newFTPGUI(0) { url->setFocus(); setGeometry(krMainWindow->x() + krMainWindow->width() / 2 - width() / 2, krMainWindow->y() + krMainWindow->height() / 2 - height() / 2, width(), height()); } void newFTPSub::accept() { url->addToHistory(url->currentText()); // save the history and completion list when the history combo is // destroyed KConfigGroup group(krConfig, "Private"); QStringList list = url->completionObject()->items(); group.writeEntry("newFTP Completion list", list); list = url->historyItems(); group.writeEntry("newFTP History list", list); QString protocol = prefix->currentText(); group.writeEntry("newFTP Protocol", protocol); newFTPGUI::accept(); } void newFTPSub::reject() { url->lineEdit()->setText(""); newFTPGUI::reject(); } /////////////////////////// KRMaskChoiceSub /////////////////////////////// KRMaskChoiceSub::KRMaskChoiceSub(QWidget * parent) : KRMaskChoice(parent) { PixmapLabel1->setPixmap(krLoader->loadIcon("edit-select", KIconLoader::Desktop, 32)); label->setText(i18n("Enter a selection:")); // the predefined selections list KConfigGroup group(krConfig, "Private"); QStringList lst = group.readEntry("Predefined Selections", QStringList()); if (lst.size() > 0) preSelections->addItems(lst); // the combo-box tweaks selection->setDuplicatesEnabled(false); selection->addItems(KRSpWidgets::maskList); selection->lineEdit()->setText("*"); selection->lineEdit()->selectAll(); selection->setFocus(); } void KRMaskChoiceSub::reject() { selection->clear(); KRMaskChoice::reject(); } void KRMaskChoiceSub::accept() { bool add = true; // make sure we don't have that already for (int i = 0; i != KRSpWidgets::maskList.count(); i++) if (KRSpWidgets::maskList[ i ].simplified() == selection->currentText().simplified()) { // break if we found one such as this add = false; break; } if (add) KRSpWidgets::maskList.insert(0, selection->currentText().toLocal8Bit()); // write down the predefined selections list QStringList list; for (int j = 0; j != preSelections->count(); j++) { QListWidgetItem *i = preSelections->item(j); list.append(i->text()); } KConfigGroup group(krConfig, "Private"); group.writeEntry("Predefined Selections", list); KRMaskChoice::accept(); } void KRMaskChoiceSub::addSelection() { QString temp = selection->currentText(); bool itemExists = false; // check if the selection already exists for (int j = 0; j != preSelections->count(); j++) { QListWidgetItem *i = preSelections->item(j); if (i->text() == temp) { itemExists = true; break; } } if (!temp.isEmpty() && !itemExists) { preSelections->addItem(selection->currentText()); preSelections->update(); } } void KRMaskChoiceSub::deleteSelection() { delete preSelections->currentItem(); preSelections->update(); } void KRMaskChoiceSub::clearSelections() { preSelections->clear(); preSelections->update(); } void KRMaskChoiceSub::acceptFromList(QListWidgetItem *i) { selection->addItem(i->text(), 0); accept(); } void KRMaskChoiceSub::currentItemChanged(QListWidgetItem *i) { if (i) selection->setEditText(i->text()); } diff --git a/krusader/Dialogs/krspwidgets.h b/krusader/Dialogs/krspwidgets.h index 946a8ed8..4c90304e 100644 --- a/krusader/Dialogs/krspwidgets.h +++ b/krusader/Dialogs/krspwidgets.h @@ -1,92 +1,83 @@ -/*************************************************************************** - krspwidgets.h - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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(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(); void accept(); }; /////////////////////////// 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(); void deleteSelection(); void clearSelections(); void acceptFromList(QListWidgetItem *i); void currentItemChanged(QListWidgetItem *i); protected: void reject(); void accept(); }; #endif diff --git a/krusader/Dialogs/kurllistrequester.cpp b/krusader/Dialogs/kurllistrequester.cpp index 1c3437b7..dcfa33dd 100644 --- a/krusader/Dialogs/kurllistrequester.cpp +++ b/krusader/Dialogs/kurllistrequester.cpp @@ -1,200 +1,190 @@ -/*************************************************************************** - kurllistrequester.cpp - description - ------------------- - copyright : (C) 2005 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kurllistrequester.h" #include "../FileSystem/filesystem.h" // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include #include #define DELETE_ITEM_ID 100 KURLListRequester::KURLListRequester(Mode requestMode, QWidget *parent) : QWidget(parent), mode(requestMode) { // Creating the widget QGridLayout *urlListRequesterGrid = new QGridLayout(this); urlListRequesterGrid->setSpacing(0); urlListRequesterGrid->setContentsMargins(0, 0, 0, 0); urlLineEdit = new KLineEdit(this); urlListRequesterGrid->addWidget(urlLineEdit, 0, 0); urlListBox = new KrListWidget(this); urlListBox->setSelectionMode(QAbstractItemView::ExtendedSelection); urlListRequesterGrid->addWidget(urlListBox, 1, 0, 1, 3); urlAddBtn = new QToolButton(this); urlAddBtn->setText(""); urlAddBtn->setIcon(QIcon::fromTheme("arrow-down")); urlListRequesterGrid->addWidget(urlAddBtn, 0, 1); urlBrowseBtn = new QToolButton(this); urlBrowseBtn->setText(""); urlBrowseBtn->setIcon(QIcon::fromTheme("folder")); urlListRequesterGrid->addWidget(urlBrowseBtn, 0, 2); // add shell completion completion.setMode(KUrlCompletion::FileCompletion); urlLineEdit->setCompletionObject(&completion); // connection table connect(urlAddBtn, SIGNAL(clicked()), this, SLOT(slotAdd())); connect(urlBrowseBtn, SIGNAL(clicked()), this, SLOT(slotBrowse())); connect(urlLineEdit, SIGNAL(returnPressed(QString)), this, SLOT(slotAdd())); connect(urlListBox, SIGNAL(itemRightClicked(QListWidgetItem*,QPoint)), this, SLOT(slotRightClicked(QListWidgetItem*,QPoint))); connect(urlLineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); } void KURLListRequester::slotAdd() { QString text = urlLineEdit->text().simplified(); if (text.length()) { QString error; emit checkValidity(text, error); if (!error.isNull()) KMessageBox::error(this, error); else { urlListBox->addItem(text); urlLineEdit->clear(); emit changed(); } } } void KURLListRequester::slotBrowse() { QUrl url; switch (mode) { case RequestFiles: url = QFileDialog::getOpenFileUrl(this); break; case RequestDirs: url = QFileDialog::getExistingDirectoryUrl(this); break; } if (!url.isEmpty()) urlLineEdit->setText(url.toDisplayString(QUrl::PreferLocalFile)); urlLineEdit->setFocus(); } void KURLListRequester::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Delete) { if (urlListBox->hasFocus()) { deleteSelectedItems(); return; } } QWidget::keyPressEvent(e); } void KURLListRequester::deleteSelectedItems() { QList delList = urlListBox->selectedItems(); for (int i = 0; i != delList.count(); i++) delete delList[ i ]; emit changed(); } void KURLListRequester::slotRightClicked(QListWidgetItem *item, const QPoint &pos) { if (item == 0) return; QMenu popupMenu(this); QAction * menuAction = popupMenu.addAction(i18n("Delete")); if (menuAction == popupMenu.exec(pos)) { if (item->isSelected()) deleteSelectedItems(); else { delete item; emit changed(); } } } QList KURLListRequester::urlList() { QList urls; QString text = urlLineEdit->text().simplified(); if (!text.isEmpty()) { QString error; emit checkValidity(text, error); if (error.isNull()) urls.append(QUrl::fromUserInput(text, QString(), QUrl::AssumeLocalFile)); } for (int i = 0; i != urlListBox->count(); i++) { QListWidgetItem *item = urlListBox->item(i); QString text = item->text().simplified(); QString error; emit checkValidity(text, error); if (error.isNull()) urls.append(QUrl::fromUserInput(text, QString(), QUrl::AssumeLocalFile)); } return urls; } void KURLListRequester::setUrlList(QList urlList) { urlLineEdit->clear(); urlListBox->clear(); QList::iterator it; for (it = urlList.begin(); it != urlList.end(); ++it) urlListBox->addItem(it->toDisplayString(QUrl::PreferLocalFile)); emit changed(); } diff --git a/krusader/Dialogs/kurllistrequester.h b/krusader/Dialogs/kurllistrequester.h index 5c710dc3..f3fa1e26 100644 --- a/krusader/Dialogs/kurllistrequester.h +++ b/krusader/Dialogs/kurllistrequester.h @@ -1,91 +1,81 @@ -/*************************************************************************** - kurllistrequester.h - description - ------------------- - copyright : (C) 2005 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KURLLISTREQUESTER_H #define KURLLISTREQUESTER_H // QtGui #include // QtWidgets #include #include #include #include #include "../GUI/krlistwidget.h" class KURLListRequester : public QWidget { Q_OBJECT public: enum Mode { RequestFiles, RequestDirs }; explicit KURLListRequester(Mode requestMode, QWidget *parent = 0); QList urlList(); void setUrlList(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: virtual void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; void deleteSelectedItems(); Mode mode; KLineEdit *urlLineEdit; KrListWidget *urlListBox; QToolButton *urlAddBtn; QToolButton *urlBrowseBtn; KUrlCompletion completion; }; #endif /* __KURLLISTREQUESTER_H__ */ diff --git a/krusader/Dialogs/packgui.cpp b/krusader/Dialogs/packgui.cpp index d65ceb00..b6bf1794 100644 --- a/krusader/Dialogs/packgui.cpp +++ b/krusader/Dialogs/packgui.cpp @@ -1,136 +1,127 @@ -/*************************************************************************** - packgui.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "packgui.h" #include "../krglobal.h" #include "../defaults.h" // QtCore #include // QtWidgets #include #include #include #include #include #include #include #include #include #define PS(x) lst.contains(x)>0 // clear the statics first QString PackGUI::filename = 0; QString PackGUI::destination = 0; QString PackGUI::type = 0; QMap PackGUI::extraProps; PackGUI::PackGUI(QString defaultName, QString defaultPath, int noOfFiles, QString filename) : PackGUIBase(0) { // first, fill the WhatToPack textfield with information if (noOfFiles == 1) TextLabel1->setText(i18n("Pack %1", filename)); else TextLabel1->setText(i18np("Pack %1 file", "Pack %1 files", noOfFiles)); // now, according to the Konfigurator, fill the combobox with the information // about what kind of packing we can do KConfigGroup group(krConfig, "Archives"); QStringList lst = group.readEntry("Supported Packers", QStringList()); // now, clear the type combo and begin... typeData->clear(); if (PS("tar")) typeData->addItem("tar"); if (PS("tar") && PS("gzip")) typeData->addItem("tar.gz"); if (PS("tar") && PS("bzip2")) typeData->addItem("tar.bz2"); if (PS("tar") && PS("lzma")) typeData->addItem("tar.lzma"); if (PS("tar") && PS("xz")) typeData->addItem("tar.xz"); if (PS("zip")) typeData->addItem("zip"); if (PS("zip")) typeData->addItem("cbz"); if (PS("rar")) typeData->addItem("rar"); if (PS("rar")) typeData->addItem("cbr"); if (PS("lha")) typeData->addItem("lha"); if (PS("arj")) typeData->addItem("arj"); if (PS("7z")) typeData->addItem("7z"); // set the last used packer as the top one QString tmp = group.readEntry("lastUsedPacker", QString()); if (!tmp.isEmpty()) { for (int i = 0; i < typeData->count(); ++i) if (typeData->itemText(i) == tmp) { typeData->removeItem(i); typeData->insertItem(0, tmp); typeData->setCurrentIndex(0); break; } } checkConsistency(); // and go on with the normal stuff dirData->setText(defaultPath); nameData->setText(defaultName); nameData->setFocus(); if (typeData->count() == 0) // if no packers are available okButton->setEnabled(false); setGeometry(krMainWindow->x() + krMainWindow->width() / 2 - width() / 2, krMainWindow->y() + krMainWindow->height() / 2 - height() / 2, width(), height()); exec(); } void PackGUI::browse() { QString temp = QFileDialog::getExistingDirectory(0, i18n("Please select a folder"), dirData->text()); if (!temp.isEmpty()) { dirData->setText(temp); } } void PackGUI::accept() { if (!extraProperties(extraProps)) return; filename = nameData->text(); destination = dirData->text(); type = typeData->currentText(); // write down the packer chosen, to be lastUsedPacker KConfigGroup group(krConfig, "Archives"); group.writeEntry("lastUsedPacker", type); krConfig->sync(); PackGUIBase::accept(); } void PackGUI::reject() { filename.clear(); destination.clear(); type.clear(); PackGUIBase::reject(); } diff --git a/krusader/Dialogs/packgui.h b/krusader/Dialogs/packgui.h index 521dc2a6..5d670c51 100644 --- a/krusader/Dialogs/packgui.h +++ b/krusader/Dialogs/packgui.h @@ -1,54 +1,45 @@ -/*************************************************************************** - packgui.h - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef PACKGUI_H #define PACKGUI_H #include "packguibase.h" class PackGUI : public PackGUIBase { Q_OBJECT public: PackGUI(QString defaultName, QString defaultPath, int noOfFiles, QString filename = ""); public slots: void browse(); protected slots: void accept(); void reject(); public: static QString filename, destination, type; static QMap extraProps; }; #endif diff --git a/krusader/Dialogs/packguibase.cpp b/krusader/Dialogs/packguibase.cpp index fab96ec9..0ddb3a5b 100644 --- a/krusader/Dialogs/packguibase.cpp +++ b/krusader/Dialogs/packguibase.cpp @@ -1,505 +1,496 @@ -/*************************************************************************** - packguibase.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "packguibase.h" // QtCore #include // QtGui #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../defaults.h" #include "../krglobal.h" /* * Constructs a PackGUIBase which is a child of 'parent', with the * name 'name' and widget flags set to 'f' * * The dialog will by default be modeless, unless you set 'modal' to * TRUE to construct a modal dialog. */ PackGUIBase::PackGUIBase(QWidget* parent) : QDialog(parent), expanded(false) { KConfigGroup group(krConfig, "Archives"); setModal(true); resize(430, 140); setWindowTitle(i18n("Pack")); grid = new QGridLayout(this); grid->setSpacing(6); grid->setContentsMargins(11, 11, 11, 11); hbox = new QHBoxLayout; hbox->setSpacing(6); hbox->setContentsMargins(0, 0, 0, 0); TextLabel3 = new QLabel(this); TextLabel3->setText(i18n("To archive")); hbox->addWidget(TextLabel3); nameData = new QLineEdit(this); hbox->addWidget(nameData); typeData = new QComboBox(this); typeData->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed)); connect(typeData, SIGNAL(activated(QString)), this, SLOT(checkConsistency())); connect(typeData, SIGNAL(highlighted(QString)), this, SLOT(checkConsistency())); hbox->addWidget(typeData); grid->addLayout(hbox, 1, 0); hbox_2 = new QHBoxLayout; hbox_2->setSpacing(6); hbox_2->setContentsMargins(0, 0, 0, 0); TextLabel5 = new QLabel(this); TextLabel5->setText(i18n("In folder")); hbox_2->addWidget(TextLabel5); dirData = new QLineEdit(this); hbox_2->addWidget(dirData); browseButton = new QToolButton(this); browseButton->setIcon(SmallIcon("document-open")); hbox_2->addWidget(browseButton); QSpacerItem* spacer = new QSpacerItem(48, 20, QSizePolicy::Fixed, QSizePolicy::Fixed); hbox_2->addItem(spacer); grid->addLayout(hbox_2, 2, 0); hbox_3 = new QHBoxLayout; hbox_3->setSpacing(6); hbox_3->setContentsMargins(0, 0, 0, 0); PixmapLabel1 = new QLabel(this); PixmapLabel1->setPixmap(krLoader->loadIcon("package-x-generic", KIconLoader::Desktop, 32)); PixmapLabel1->setScaledContents(true); PixmapLabel1->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); hbox_3->addWidget(PixmapLabel1); TextLabel1 = new QLabel(this); TextLabel1->setText(i18n("Pack")); hbox_3->addWidget(TextLabel1); grid->addLayout(hbox_3, 0, 0); hbox_4 = new QHBoxLayout; hbox_4->setSpacing(6); hbox_4->setContentsMargins(0, 0, 0, 0); QSpacerItem* spacer_3 = new QSpacerItem(20, 26, QSizePolicy::Fixed, QSizePolicy::Expanding); hbox_4->addItem(spacer_3); grid->addLayout(hbox_4, 3, 0); advancedWidget = new QWidget(this); hbox_5 = new QGridLayout(advancedWidget); hbox_5->setSpacing(6); hbox_5->setContentsMargins(0, 0, 0, 0); QVBoxLayout *compressLayout = new QVBoxLayout; compressLayout->setSpacing(6); compressLayout->setContentsMargins(0, 0, 0, 0); multipleVolume = new QCheckBox(i18n("Multiple volume archive"), advancedWidget); connect(multipleVolume, SIGNAL(toggled(bool)), this, SLOT(checkConsistency())); compressLayout->addWidget(multipleVolume, 0, 0); QHBoxLayout * volumeHbox = new QHBoxLayout; QSpacerItem* spacer_5 = new QSpacerItem(20, 26, QSizePolicy::Fixed, QSizePolicy::Fixed); volumeHbox->addItem(spacer_5); TextLabel7 = new QLabel(i18n("Size:"), advancedWidget); volumeHbox->addWidget(TextLabel7); volumeSpinBox = new QSpinBox(advancedWidget); volumeSpinBox->setMinimum(1); volumeSpinBox->setMaximum(9999); volumeSpinBox->setValue(1440); volumeHbox->addWidget(volumeSpinBox); volumeUnitCombo = new QComboBox(advancedWidget); volumeUnitCombo->addItem("B"); volumeUnitCombo->addItem("KB"); volumeUnitCombo->addItem("MB"); volumeUnitCombo->setCurrentIndex(1); volumeHbox->addWidget(volumeUnitCombo); compressLayout->addLayout(volumeHbox); int level = group.readEntry("Compression level", _defaultCompressionLevel); setCompressionLevel = new QCheckBox(i18n("Set compression level"), advancedWidget); if (level != _defaultCompressionLevel) setCompressionLevel->setChecked(true); connect(setCompressionLevel, SIGNAL(toggled(bool)), this, SLOT(checkConsistency())); compressLayout->addWidget(setCompressionLevel, 0, 0); QHBoxLayout * sliderHbox = new QHBoxLayout; QSpacerItem* spacer_6 = new QSpacerItem(20, 26, QSizePolicy::Fixed, QSizePolicy::Fixed); sliderHbox->addItem(spacer_6); QWidget * sliderVBoxWidget = new QWidget(advancedWidget); QVBoxLayout *sliderVBox = new QVBoxLayout(sliderVBoxWidget); compressionSlider = new QSlider(Qt::Horizontal, sliderVBoxWidget); compressionSlider->setMinimum(1); compressionSlider->setMaximum(9); compressionSlider->setPageStep(1); compressionSlider->setValue(level); compressionSlider->setTickPosition(QSlider::TicksBelow); sliderVBox->addWidget(compressionSlider); QWidget * minmaxWidget = new QWidget(sliderVBoxWidget); sliderVBox->addWidget(minmaxWidget); QHBoxLayout * minmaxHbox = new QHBoxLayout(minmaxWidget); minLabel = new QLabel(i18n("MIN"), minmaxWidget); maxLabel = new QLabel(i18n("MAX"), minmaxWidget); maxLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); minmaxHbox->addWidget(minLabel); minmaxHbox->addWidget(maxLabel); sliderHbox->addWidget(sliderVBoxWidget); compressLayout->addLayout(sliderHbox); compressLayout->addStretch(0); hbox_5->addLayout(compressLayout, 0, 0); QFrame *vline = new QFrame(advancedWidget); vline->setFrameStyle(QFrame::VLine | QFrame::Sunken); vline->setMinimumWidth(20); hbox_5->addWidget(vline, 0, 1); QGridLayout * passwordGrid = new QGridLayout; passwordGrid->setSpacing(6); passwordGrid->setContentsMargins(0, 0, 0, 0); TextLabel4 = new QLabel(advancedWidget); TextLabel4->setText(i18n("Password")); passwordGrid->addWidget(TextLabel4, 0, 0); password = new QLineEdit(advancedWidget); password->setEchoMode(QLineEdit::Password); connect(password, SIGNAL(textChanged(QString)), this, SLOT(checkConsistency())); passwordGrid->addWidget(password, 0, 1); TextLabel6 = new QLabel(advancedWidget); TextLabel6->setText(i18n("Again")); passwordGrid->addWidget(TextLabel6, 1, 0); passwordAgain = new QLineEdit(advancedWidget); passwordAgain->setEchoMode(QLineEdit::Password); connect(passwordAgain, SIGNAL(textChanged(QString)), this, SLOT(checkConsistency())); passwordGrid->addWidget(passwordAgain, 1, 1); QHBoxLayout *consistencyHbox = new QHBoxLayout; QSpacerItem* spacer_cons = new QSpacerItem(48, 20, QSizePolicy::Expanding, QSizePolicy::Fixed); consistencyHbox->addItem(spacer_cons); passwordConsistencyLabel = new QLabel(advancedWidget); consistencyHbox->addWidget(passwordConsistencyLabel); passwordGrid->addLayout(consistencyHbox, 2, 0, 1, 2); encryptHeaders = new QCheckBox(i18n("Encrypt headers"), advancedWidget); passwordGrid->addWidget(encryptHeaders, 3, 0, 1, 2); QSpacerItem* spacer_psw = new QSpacerItem(20, 20, QSizePolicy::Fixed, QSizePolicy::Expanding); passwordGrid->addItem(spacer_psw, 4, 0); hbox_5->addLayout(passwordGrid, 0, 2); hbox_7 = new QHBoxLayout; hbox_7->setSpacing(6); hbox_7->setContentsMargins(0, 0, 0, 0); TextLabel8 = new QLabel(i18n("Command line switches:"), advancedWidget); TextLabel8->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); hbox_7->addWidget(TextLabel8); commandLineSwitches = new KHistoryComboBox(advancedWidget); commandLineSwitches->setMaxCount(25); // remember 25 items commandLineSwitches->setDuplicatesEnabled(false); commandLineSwitches->setMinimumContentsLength(10); QStringList list = group.readEntry("Command Line Switches", QStringList()); commandLineSwitches->setHistoryItems(list); hbox_7->addWidget(commandLineSwitches); hbox_5->addLayout(hbox_7, 1, 0, 1, 3); advancedWidget->hide(); checkConsistency(); grid->addWidget(advancedWidget, 4, 0); hbox_6 = new QHBoxLayout; hbox_6->setSpacing(6); hbox_6->setContentsMargins(0, 0, 0, 0); advancedButton = new QPushButton(this); advancedButton->setText(i18n("&Advanced >>")); hbox_6->addWidget(advancedButton); QSpacerItem* spacer_2 = new QSpacerItem(140, 20, QSizePolicy::Expanding, QSizePolicy::Fixed); hbox_6->addItem(spacer_2); okButton = new QPushButton(this); KStandardGuiItem::assign(okButton, KStandardGuiItem::Ok); okButton->setDefault(true); hbox_6->addWidget(okButton); cancelButton = new QPushButton(this); KStandardGuiItem::assign(cancelButton, KStandardGuiItem::Cancel); hbox_6->addWidget(cancelButton); grid->addLayout(hbox_6, 6, 0); // signals and slots connections connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); connect(advancedButton, SIGNAL(clicked()), this, SLOT(expand())); connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); connect(browseButton, SIGNAL(clicked()), this, SLOT(browse())); } /* * Destroys the object and frees any allocated resources */ PackGUIBase::~PackGUIBase() { // no need to delete child widgets, Qt does it all for us } void PackGUIBase::browse() { qWarning("PackGUIBase::browse(): Not implemented yet!"); } void PackGUIBase::expand() { expanded = !expanded; advancedButton->setText(expanded ? i18n("&Advanced <<") : i18n("&Advanced >>")); if (expanded) advancedWidget->show(); else { advancedWidget->hide(); layout()->activate(); QSize minSize = minimumSize(); resize(width(), minSize.height()); } show(); } void PackGUIBase::checkConsistency() { QPalette p = QGuiApplication::palette(); QPalette pal = passwordConsistencyLabel->palette(); if (password->text().isEmpty() && passwordAgain->text().isEmpty()) { pal.setColor(passwordConsistencyLabel->foregroundRole(), p.color(QPalette::Active, QPalette::Text)); passwordConsistencyLabel->setText(i18n("No password specified")); } else if (password->text() == passwordAgain->text()) { pal.setColor(passwordConsistencyLabel->foregroundRole(), p.color(QPalette::Active, QPalette::Text)); passwordConsistencyLabel->setText(i18n("The passwords are equal")); } else { pal.setColor(passwordConsistencyLabel->foregroundRole(), Qt::red); passwordConsistencyLabel->setText(i18n("The passwords are different")); } passwordConsistencyLabel->setPalette(pal); QString packer = typeData->currentText(); bool passworded = false; if (packer == "7z" || packer == "rar" || packer == "zip" || packer == "arj") passworded = true; passwordConsistencyLabel->setEnabled(passworded); password->setEnabled(passworded); passwordAgain->setEnabled(passworded); TextLabel4->setEnabled(passworded); TextLabel6->setEnabled(passworded); encryptHeaders->setEnabled(packer == "rar"); multipleVolume->setEnabled(packer == "rar" || packer == "arj"); bool volumeEnabled = multipleVolume->isEnabled() && multipleVolume->isChecked(); volumeSpinBox->setEnabled(volumeEnabled); volumeUnitCombo->setEnabled(volumeEnabled); TextLabel7->setEnabled(volumeEnabled); /* TODO */ setCompressionLevel->setEnabled(packer == "rar" || packer == "arj" || packer == "zip" || packer == "7z"); bool sliderEnabled = setCompressionLevel->isEnabled() && setCompressionLevel->isChecked(); compressionSlider->setEnabled(sliderEnabled); minLabel->setEnabled(sliderEnabled); maxLabel->setEnabled(sliderEnabled); } bool PackGUIBase::extraProperties(QMap & inMap) { inMap.clear(); KConfigGroup group(krConfig, "Archives"); if (password->isEnabled() && passwordAgain->isEnabled()) { if (password->text() != passwordAgain->text()) { KMessageBox::error(this, i18n("Cannot pack, the passwords are different.")); return false; } if (!password->text().isEmpty()) { inMap[ "Password" ] = password->text(); if (encryptHeaders->isEnabled() && encryptHeaders->isChecked()) inMap[ "EncryptHeaders" ] = '1'; } } if (multipleVolume->isEnabled() && multipleVolume->isChecked()) { KIO::filesize_t size = volumeSpinBox->value(); switch (volumeUnitCombo->currentIndex()) { case 2: size *= 1000; #if __GNUC__ >= 7 [[gnu::fallthrough]]; #endif case 1: size *= 1000; default: break; } if (size < 10000) { KMessageBox::error(this, i18n("Invalid volume size.")); return false; } QString sbuffer; sbuffer.sprintf("%llu", size); inMap[ "VolumeSize" ] = sbuffer; } if (setCompressionLevel->isEnabled() && setCompressionLevel->isChecked()) { inMap[ "CompressionLevel" ] = QString("%1").arg(compressionSlider->value()); int level = compressionSlider->value(); group.writeEntry("Compression level", level); } QString cmdArgs = commandLineSwitches->currentText().trimmed(); if (!cmdArgs.isEmpty()) { bool firstChar = true; QChar quote = QChar::Null; for (int i = 0; i < cmdArgs.length(); i++) { QChar ch(cmdArgs[ i ]); if (ch.isSpace()) continue; if (ch == quote) { quote = QChar::Null; continue; } if (firstChar && ch != QLatin1Char('-')) { KMessageBox::error(this, i18n("Invalid command line switch.\nA switch must start with '-'.")); return false; } firstChar = false; if (quote == QLatin1Char('"')) continue; if (quote == QChar::Null && (ch == QLatin1Char('\'') || ch == QLatin1Char('"'))) quote = ch; if (ch == QLatin1Char('\\')) { if (i == cmdArgs.length() - 1) { KMessageBox::error(this, i18n("Invalid command line switch.\nBackslashes cannot be the last character.")); return false; } i++; } } if (quote != QChar::Null) { KMessageBox::error(this, i18n("Invalid command line switch.\nUnclosed quotation mark.")); return false; } commandLineSwitches->addToHistory(cmdArgs); QStringList list = commandLineSwitches->historyItems(); group.writeEntry("Command Line Switches", list); inMap[ "CommandLineSwitches" ] = cmdArgs; } return true; } diff --git a/krusader/Dialogs/packguibase.h b/krusader/Dialogs/packguibase.h index 48c36b19..6538eedb 100644 --- a/krusader/Dialogs/packguibase.h +++ b/krusader/Dialogs/packguibase.h @@ -1,112 +1,103 @@ -/*************************************************************************** - packguibase.h - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef PACKGUIBASE_H #define PACKGUIBASE_H // QtCore #include // QtWidgets #include #include #include #include #include class QHBoxLayout; class QGridLayout; class QCheckBox; class QComboBox; class QLabel; class QLineEdit; class QPushButton; class QToolButton; class QSpinBox; class QSlider; class KHistoryComboBox; class PackGUIBase : public QDialog { Q_OBJECT public: explicit PackGUIBase(QWidget* parent = 0); ~PackGUIBase(); QLabel* TextLabel3; QLineEdit* nameData; QComboBox* typeData; QLabel* TextLabel5; QLineEdit* dirData; QToolButton* browseButton; QWidget* advancedWidget; QLabel* PixmapLabel1; QLabel* TextLabel1; QLabel* TextLabel4; QLabel* TextLabel6; QLabel* TextLabel7; QLabel* TextLabel8; QLabel* minLabel; QLabel* maxLabel; QLineEdit* password; QLineEdit* passwordAgain; QLabel* passwordConsistencyLabel; QPushButton* okButton; QPushButton* cancelButton; QPushButton* advancedButton; QCheckBox* encryptHeaders; QCheckBox* multipleVolume; QSpinBox* volumeSpinBox; QComboBox* volumeUnitCombo; QCheckBox* setCompressionLevel; QSlider* compressionSlider; KHistoryComboBox *commandLineSwitches; public slots: virtual void browse(); virtual bool extraProperties(QMap &); void expand(); void checkConsistency(); protected: QHBoxLayout* hbox; QHBoxLayout* hbox_2; QHBoxLayout* hbox_3; QHBoxLayout* hbox_4; QGridLayout* hbox_5; QHBoxLayout* hbox_6; QHBoxLayout* hbox_7; QGridLayout* grid; private: bool expanded; }; #endif // PACKGUIBASE_H diff --git a/krusader/Dialogs/percentalsplitter.cpp b/krusader/Dialogs/percentalsplitter.cpp index 7fcda401..d17d80b0 100644 --- a/krusader/Dialogs/percentalsplitter.cpp +++ b/krusader/Dialogs/percentalsplitter.cpp @@ -1,93 +1,83 @@ -/*************************************************************************** - percentalsplitter.h - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "percentalsplitter.h" // QtCore #include // QtGui #include #include // QtWidgets #include #include #include #include PercentalSplitter::PercentalSplitter(QWidget * parent) : QSplitter(parent), label(0), opaqueOldPos(-1) { connect(this, SIGNAL(splitterMoved(int,int)), SLOT(slotSplitterMoved(int,int))); } PercentalSplitter::~PercentalSplitter() { } QString PercentalSplitter::toolTipString(int p) { QList values = sizes(); if (values.count() != 0) { int sum = 0; QListIterator it(values); while (it.hasNext()) sum += it.next(); if (sum == 0) sum++; int percent = (int)(((double)p / (double)(sum)) * 10000. + 0.5); return QString("%1.%2%3").arg(percent / 100).arg((percent / 10) % 10).arg(percent % 10) + '%'; } return QString(); } void PercentalSplitter::slotSplitterMoved(int p, int index) { handle(index) -> setToolTip(toolTipString(p)); QToolTip::showText(QCursor::pos(), toolTipString(p) , this); } void PercentalSplitter::showEvent(QShowEvent * event) { QList values = sizes(); for (int i = 0; i != count(); i++) { int p = 0; for (int j = 0; j < i; j++) p += values[ j ]; handle(i) -> setToolTip(toolTipString(p)); } QSplitter::showEvent(event); } diff --git a/krusader/Dialogs/percentalsplitter.h b/krusader/Dialogs/percentalsplitter.h index 2c49e0e3..5e81235a 100644 --- a/krusader/Dialogs/percentalsplitter.h +++ b/krusader/Dialogs/percentalsplitter.h @@ -1,60 +1,50 @@ -/*************************************************************************** - percentalsplitter.h - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef PERCENTALSPLITTER_H #define PERCENTALSPLITTER_H // QtWidgets #include #include class PercentalSplitter : public QSplitter { Q_OBJECT public: explicit PercentalSplitter(QWidget * parent = 0); virtual ~PercentalSplitter(); QString toolTipString(int p); protected: virtual void showEvent(QShowEvent * event) Q_DECL_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.cpp b/krusader/DiskUsage/diskusage.cpp index 94c95fd4..530c4050 100644 --- a/krusader/DiskUsage/diskusage.cpp +++ b/krusader/DiskUsage/diskusage.cpp @@ -1,1143 +1,1133 @@ -/*************************************************************************** - diskusage.cpp - description - ------------------- - copyright : (C) 2004 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "diskusage.h" // QtCore #include #include #include #include #include #include // QtGui #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dufilelight.h" #include "dulines.h" #include "dulistview.h" #include "filelightParts/Config.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/filesystemprovider.h" #include "../FileSystem/krpermhandler.h" #include "../Panel/krpanel.h" #include "../Panel/panelfunc.h" #include "../defaults.h" #include "../kicons.h" #include "../krglobal.h" // these are the values that will exist in the menu #define DELETE_ID 90 #define EXCLUDE_ID 91 #define PARENT_DIR_ID 92 #define NEW_SEARCH_ID 93 #define REFRESH_ID 94 #define STEP_INTO_ID 95 #define INCLUDE_ALL_ID 96 #define VIEW_POPUP_ID 97 #define LINES_VIEW_ID 98 #define DETAILED_VIEW_ID 99 #define FILELIGHT_VIEW_ID 100 #define NEXT_VIEW_ID 101 #define PREVIOUS_VIEW_ID 102 #define ADDITIONAL_POPUP_ID 103 #define MAX_FILENUM 100 LoaderWidget::LoaderWidget(QWidget *parent) : QScrollArea(parent), cancelled(false) { QPalette palette = viewport()->palette(); palette.setColor(viewport()->backgroundRole(), Qt::white); viewport()->setPalette(palette); widget = new QWidget(parent); QGridLayout *loaderLayout = new QGridLayout(widget); loaderLayout->setSpacing(0); loaderLayout->setContentsMargins(0, 0, 0, 0); QFrame *loaderBox = new QFrame(widget); loaderBox->setFrameShape(QFrame::Box); loaderBox->setFrameShadow(QFrame::Sunken); loaderBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); loaderBox->setFrameStyle(QFrame::Panel + QFrame::Raised); loaderBox->setLineWidth(2); QGridLayout *synchGrid = new QGridLayout(loaderBox); synchGrid->setSpacing(6); synchGrid->setContentsMargins(11, 11, 11, 11); QLabel *titleLabel = new QLabel(i18n("Loading Usage Information"), loaderBox); titleLabel->setAlignment(Qt::AlignHCenter); synchGrid->addWidget(titleLabel, 0, 0, 1, 2); QLabel *filesLabel = new QLabel(i18n("Files:"), loaderBox); filesLabel->setFrameShape(QLabel::StyledPanel); filesLabel->setFrameShadow(QLabel::Sunken); synchGrid->addWidget(filesLabel, 1, 0); QLabel *directoriesLabel = new QLabel(i18n("Directories:"), loaderBox); directoriesLabel->setFrameShape(QLabel::StyledPanel); directoriesLabel->setFrameShadow(QLabel::Sunken); synchGrid->addWidget(directoriesLabel, 2, 0); QLabel *totalSizeLabel = new QLabel(i18n("Total Size:"), loaderBox); totalSizeLabel->setFrameShape(QLabel::StyledPanel); totalSizeLabel->setFrameShadow(QLabel::Sunken); synchGrid->addWidget(totalSizeLabel, 3, 0); files = new QLabel(loaderBox); files->setFrameShape(QLabel::StyledPanel); files->setFrameShadow(QLabel::Sunken); files->setAlignment(Qt::AlignRight); synchGrid->addWidget(files, 1, 1); directories = new QLabel(loaderBox); directories->setFrameShape(QLabel::StyledPanel); directories->setFrameShadow(QLabel::Sunken); directories->setAlignment(Qt::AlignRight); synchGrid->addWidget(directories, 2, 1); totalSize = new QLabel(loaderBox); totalSize->setFrameShape(QLabel::StyledPanel); totalSize->setFrameShadow(QLabel::Sunken); totalSize->setAlignment(Qt::AlignRight); synchGrid->addWidget(totalSize, 3, 1); int width; searchedDirectory = new KSqueezedTextLabel(loaderBox); searchedDirectory->setFrameShape(QLabel::StyledPanel); searchedDirectory->setFrameShadow(QLabel::Sunken); searchedDirectory->setMinimumWidth(width = QFontMetrics(searchedDirectory->font()).width("W") * 30); searchedDirectory->setMaximumWidth(width); synchGrid->addWidget(searchedDirectory, 4, 0, 1, 2); QFrame *line = new QFrame(loaderBox); line->setFrameStyle(QFrame::HLine | QFrame::Sunken); synchGrid->addWidget(line, 5, 0, 1, 2); QWidget *hboxWidget = new QWidget(loaderBox); QHBoxLayout * hbox = new QHBoxLayout(hboxWidget); QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); hbox->addItem(spacer); QPushButton *cancelButton = new QPushButton(hboxWidget); KStandardGuiItem::assign(cancelButton, KStandardGuiItem::Cancel); hbox->addWidget(cancelButton); synchGrid->addWidget(hboxWidget, 6, 1); loaderLayout->addWidget(loaderBox, 0, 0); setWidget(widget); setAlignment(Qt::AlignCenter); connect(cancelButton, SIGNAL(clicked()), this, SLOT(slotCancelled())); } void LoaderWidget::init() { cancelled = false; } void LoaderWidget::setCurrentURL(const QUrl &url) { searchedDirectory->setText(FileSystem::ensureTrailingSlash(url).toDisplayString(QUrl::PreferLocalFile)); } void LoaderWidget::setValues(int fileNum, int dirNum, KIO::filesize_t total) { files->setText(QString("%1").arg(fileNum)); directories->setText(QString("%1").arg(dirNum)); totalSize->setText(QString("%1").arg(KRpermHandler::parseSize(total).trimmed())); } void LoaderWidget::slotCancelled() { cancelled = true; } DiskUsage::DiskUsage(QString confGroup, QWidget *parent) : QStackedWidget(parent), currentDirectory(0), root(0), configGroup(confGroup), loading(false), abortLoading(false), clearAfterAbort(false), deleting(false), searchFileSystem(0) { listView = new DUListView(this); lineView = new DULines(this); filelightView = new DUFilelight(this); loaderView = new LoaderWidget(this); addWidget(listView); addWidget(lineView); addWidget(filelightView); addWidget(loaderView); setView(VIEW_LINES); Filelight::Config::read(); connect(&loadingTimer, SIGNAL(timeout()), this, SLOT(slotLoadDirectory())); } DiskUsage::~DiskUsage() { if (listView) // don't remove these lines. The module will crash at exit if removed delete listView; if (lineView) delete lineView; if (filelightView) delete filelightView; if (root) delete root; QHashIterator< File *, Properties * > lit(propertyMap); while (lit.hasNext()) delete lit.next().value(); } void DiskUsage::load(const QUrl &baseDir) { fileNum = dirNum = 0; currentSize = 0; emit status(i18n("Loading the disk usage information...")); clear(); baseURL = baseDir.adjusted(QUrl::StripTrailingSlash); root = new Directory(baseURL.fileName(), baseDir.toDisplayString(QUrl::PreferLocalFile)); directoryStack.clear(); parentStack.clear(); directoryStack.push(""); parentStack.push(root); if (searchFileSystem) { delete searchFileSystem; searchFileSystem = 0; } searchFileSystem = FileSystemProvider::instance().getFilesystem(baseDir); if (searchFileSystem == 0) { qWarning() << "could not get filesystem for directory=" << baseDir; loading = abortLoading = clearAfterAbort = false; emit loadFinished(false); return; } currentFileItem = 0; if (!loading) { viewBeforeLoad = activeView; setView(VIEW_LOADER); } loading = true; loaderView->init(); loaderView->setCurrentURL(baseURL); loaderView->setValues(fileNum, dirNum, currentSize); loadingTimer.setSingleShot(true); loadingTimer.start(0); } void DiskUsage::slotLoadDirectory() { if ((currentFileItem == 0 && directoryStack.isEmpty()) || loaderView->wasCancelled() || abortLoading) { if (searchFileSystem) delete searchFileSystem; searchFileSystem = 0; currentFileItem = 0; setView(viewBeforeLoad); if (clearAfterAbort) clear(); else { calculateSizes(); changeDirectory(root); } emit loadFinished(!(loaderView->wasCancelled() || abortLoading)); loading = abortLoading = clearAfterAbort = false; } else if (loading) { for (int counter = 0; counter != MAX_FILENUM; counter ++) { if (currentFileItem == 0) { if (directoryStack.isEmpty()) break; dirToCheck = directoryStack.pop(); currentParent = parentStack.pop(); contentMap.insert(dirToCheck, currentParent); QUrl url = baseURL; if (!dirToCheck.isEmpty()) { url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (dirToCheck)); } #ifdef BSD if (url.isLocalFile() && url.path().left(7) == "/procfs") break; #else if (url.isLocalFile() && url.path().left(5) == "/proc") break; #endif loaderView->setCurrentURL(url); if (!searchFileSystem->scanDir(url)) break; fileItems = searchFileSystem->fileItems(); dirNum++; currentFileItem = fileItems.isEmpty() ? 0 : fileItems.takeFirst(); } else { fileNum++; File *newItem = 0; QString mime = currentFileItem->getMime(); // fast == not using mimetype magic if (currentFileItem->isDir() && !currentFileItem->isSymLink()) { newItem = new Directory(currentParent, currentFileItem->getName(), dirToCheck, currentFileItem->getSize(), currentFileItem->getMode(), currentFileItem->getOwner(), currentFileItem->getGroup(), currentFileItem->getPerm(), currentFileItem->getTime_t(), currentFileItem->isSymLink(), mime); directoryStack.push((dirToCheck.isEmpty() ? "" : dirToCheck + '/') + currentFileItem->getName()); parentStack.push(dynamic_cast(newItem)); } else { newItem = new File(currentParent, currentFileItem->getName(), dirToCheck, currentFileItem->getSize(), currentFileItem->getMode(), currentFileItem->getOwner(), currentFileItem->getGroup(), currentFileItem->getPerm(), currentFileItem->getTime_t(), currentFileItem->isSymLink(), mime); currentSize += currentFileItem->getSize(); } currentParent->append(newItem); currentFileItem = fileItems.isEmpty() ? 0 : fileItems.takeFirst(); } } loaderView->setValues(fileNum, dirNum, currentSize); loadingTimer.setSingleShot(true); loadingTimer.start(0); } } void DiskUsage::stopLoad() { abortLoading = true; } void DiskUsage::close() { if (loading) { abortLoading = true; clearAfterAbort = true; } } void DiskUsage::dirUp() { if (currentDirectory != 0) { if (currentDirectory->parent() != 0) changeDirectory((Directory *)(currentDirectory->parent())); else { QUrl up = KIO::upUrl(baseURL); if (KMessageBox::questionYesNo(this, i18n("Stepping into the parent folder requires " "loading the content of the \"%1\" URL. Do you wish " "to continue?", up.toDisplayString(QUrl::PreferLocalFile)), i18n("Krusader::DiskUsage"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "DiskUsageLoadParentDir" ) == KMessageBox::Yes) load(up); } } } Directory * DiskUsage::getDirectory(QString dir) { while (dir.endsWith('/')) dir.truncate(dir.length() - 1); if (dir.isEmpty()) return root; if (contentMap.find(dir) == contentMap.end()) return 0; return contentMap[ dir ]; } File * DiskUsage::getFile(QString path) { if (path.isEmpty()) return root; QString dir = path; int ndx = path.lastIndexOf('/'); QString file = path.mid(ndx + 1); if (ndx == -1) dir = ""; else dir.truncate(ndx); Directory *dirEntry = getDirectory(dir); if (dirEntry == 0) return 0; for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) if ((*it)->name() == file) return *it; return 0; } void DiskUsage::clear() { baseURL = QUrl(); emit clearing(); QHashIterator< File *, Properties * > lit(propertyMap); while (lit.hasNext()) delete lit.next().value(); propertyMap.clear(); contentMap.clear(); if (root) delete root; root = currentDirectory = 0; } int DiskUsage::calculateSizes(Directory *dirEntry, bool emitSig, int depth) { int changeNr = 0; if (dirEntry == 0) dirEntry = root; KIO::filesize_t own = 0, total = 0; for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) { File * item = *it; if (!item->isExcluded()) { if (item->isDir()) changeNr += calculateSizes(dynamic_cast(item), emitSig, depth + 1); else own += item->size(); total += item->size(); } } KIO::filesize_t oldOwn = dirEntry->ownSize(), oldTotal = dirEntry->size(); dirEntry->setSizes(total, own); if (dirEntry == currentDirectory) currentSize = total; if (emitSig && (own != oldOwn || total != oldTotal)) { emit changed(dirEntry); changeNr++; } if (depth == 0 && changeNr != 0) emit changeFinished(); return changeNr; } int DiskUsage::exclude(File *file, bool calcPercents, int depth) { int changeNr = 0; if (!file->isExcluded()) { file->exclude(true); emit changed(file); changeNr++; if (file->isDir()) { Directory *dir = dynamic_cast(file); for (Iterator it = dir->iterator(); it != dir->end(); ++it) changeNr += exclude(*it, false, depth + 1); } } if (calcPercents) { calculateSizes(root, true); calculatePercents(true); createStatus(); } if (depth == 0 && changeNr != 0) emit changeFinished(); return changeNr; } int DiskUsage::include(Directory *dir, int depth) { int changeNr = 0; if (dir == 0) return 0; for (Iterator it = dir->iterator(); it != dir->end(); ++it) { File *item = *it; if (item->isDir()) changeNr += include(dynamic_cast(item), depth + 1); if (item->isExcluded()) { item->exclude(false); emit changed(item); changeNr++; } } if (depth == 0 && changeNr != 0) emit changeFinished(); return changeNr; } void DiskUsage::includeAll() { include(root); calculateSizes(root, true); calculatePercents(true); createStatus(); } int DiskUsage::del(File *file, bool calcPercents, int depth) { int deleteNr = 0; if (file == root) return 0; KConfigGroup gg(krConfig, "General"); bool trash = gg.readEntry("Move To Trash", _MoveToTrash); QUrl url = QUrl::fromLocalFile(file->fullPath()); if (calcPercents) { // now ask the user if he want to delete: KConfigGroup ga(krConfig, "Advanced"); if (ga.readEntry("Confirm Delete", _ConfirmDelete)) { QString s; KGuiItem b; if (trash && url.isLocalFile()) { s = i18nc("singularOnly", "Do you really want to move this item to the trash?"); b = KGuiItem(i18n("&Trash")); } else { s = i18nc("singularOnly", "Do you really want to delete this item?"); b = KStandardGuiItem::del(); } QStringList name; name.append(file->fullPath()); // show message // note: i'm using continue and not yes/no because the yes/no has cancel as default button if (KMessageBox::warningContinueCancelList(krMainWindow, s, name, i18n("Warning"), b) != KMessageBox::Continue) return 0; } emit status(i18n("Deleting %1...", file->name())); } if (file == currentDirectory) dirUp(); if (file->isDir()) { Directory *dir = dynamic_cast(file); Iterator it; while ((it = dir->iterator()) != dir->end()) deleteNr += del(*it, false, depth + 1); QString path; for (const Directory *d = (Directory*)file; d != root && d && d->parent() != 0; d = d->parent()) { if (!path.isEmpty()) path = '/' + path; path = d->name() + path; } contentMap.remove(path); } emit deleted(file); deleteNr++; KIO::Job *job; if (trash) { job = KIO::trash(url); } else { job = KIO::del(QUrl::fromLocalFile(file->fullPath()), KIO::HideProgressInfo); } deleting = true; // during qApp->processEvent strange things can occur grabMouse(); // that's why we disable the mouse and keyboard events grabKeyboard(); job->exec(); delete job; releaseMouse(); releaseKeyboard(); deleting = false; ((Directory *)(file->parent()))->remove(file); delete file; if (depth == 0) createStatus(); if (calcPercents) { calculateSizes(root, true); calculatePercents(true); createStatus(); emit enteringDirectory(currentDirectory); } if (depth == 0 && deleteNr != 0) emit deleteFinished(); return deleteNr; } void * DiskUsage::getProperty(File *item, QString key) { QHash< File *, Properties *>::iterator itr = propertyMap.find(item); if (itr == propertyMap.end()) return 0; QHash::iterator it = (*itr)->find(key); if (it == (*itr)->end()) return 0; return it.value(); } void DiskUsage::addProperty(File *item, QString key, void * prop) { Properties *props; QHash< File *, Properties *>::iterator itr = propertyMap.find(item); if (itr == propertyMap.end()) { props = new Properties(); propertyMap.insert(item, props); } else props = *itr; props->insert(key, prop); } void DiskUsage::removeProperty(File *item, QString key) { QHash< File *, Properties *>::iterator itr = propertyMap.find(item); if (itr == propertyMap.end()) return; (*itr)->remove(key); if ((*itr)->count() == 0) propertyMap.remove(item); } void DiskUsage::createStatus() { Directory *dirEntry = currentDirectory; if (dirEntry == 0) return; QUrl url = baseURL; if (dirEntry != root) { url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (dirEntry->directory())); } emit status(i18n("Current folder:%1, Total size:%2, Own size:%3", url.toDisplayString(QUrl::PreferLocalFile | QUrl::StripTrailingSlash), ' ' + KRpermHandler::parseSize(dirEntry->size()), ' ' + KRpermHandler::parseSize(dirEntry->ownSize()))); } void DiskUsage::changeDirectory(Directory *dir) { currentDirectory = dir; currentSize = dir->size(); calculatePercents(true, dir); createStatus(); emit enteringDirectory(dir); } Directory* DiskUsage::getCurrentDir() { return currentDirectory; } void DiskUsage::rightClickMenu(const QPoint & pos, File *fileItem, QMenu *addPopup, QString addPopupName) { QMenu popup(this); popup.setTitle(i18n("Disk Usage")); QHash actionHash; if (fileItem != 0) { QAction * actDelete = popup.addAction(i18n("Delete")); actionHash[ actDelete ] = DELETE_ID; actDelete->setShortcut(Qt::Key_Delete); QAction * actExclude = popup.addAction(i18n("Exclude")); actionHash[ actExclude ] = EXCLUDE_ID; actExclude->setShortcut(Qt::CTRL + Qt::Key_E); popup.addSeparator(); } QAction * myAct = popup.addAction(i18n("Up one folder")); actionHash[ myAct ] = PARENT_DIR_ID; myAct->setShortcut(Qt::SHIFT + Qt::Key_Up); myAct = popup.addAction(i18n("New search")); actionHash[ myAct ] = NEW_SEARCH_ID; myAct->setShortcut(Qt::CTRL + Qt::Key_N); myAct = popup.addAction(i18n("Refresh")); actionHash[ myAct ] = REFRESH_ID; myAct->setShortcut(Qt::CTRL + Qt::Key_R); myAct = popup.addAction(i18n("Include all")); actionHash[ myAct ] = INCLUDE_ALL_ID; myAct->setShortcut(Qt::CTRL + Qt::Key_I); myAct = popup.addAction(i18n("Step into")); actionHash[ myAct ] = STEP_INTO_ID; myAct->setShortcut(Qt::SHIFT + Qt::Key_Down); popup.addSeparator(); if (addPopup != 0) { QAction * menu = popup.addMenu(addPopup); menu->setText(addPopupName); } QMenu viewPopup; myAct = viewPopup.addAction(i18n("Lines")); actionHash[ myAct ] = LINES_VIEW_ID; myAct->setShortcut(Qt::CTRL + Qt::Key_L); myAct = viewPopup.addAction(i18n("Detailed")); actionHash[ myAct ] = DETAILED_VIEW_ID; myAct->setShortcut(Qt::CTRL + Qt::Key_D); myAct = viewPopup.addAction(i18n("Filelight")); actionHash[ myAct ] = FILELIGHT_VIEW_ID; myAct->setShortcut(Qt::CTRL + Qt::Key_F); viewPopup.addSeparator(); myAct = viewPopup.addAction(i18n("Next")); actionHash[ myAct ] = NEXT_VIEW_ID; myAct->setShortcut(Qt::SHIFT + Qt::Key_Right); myAct = viewPopup.addAction(i18n("Previous")); actionHash[ myAct ] = PREVIOUS_VIEW_ID; myAct->setShortcut(Qt::SHIFT + Qt::Key_Left); QAction * menu = popup.addMenu(&viewPopup); menu->setText(i18n("View")); QAction * res = popup.exec(pos); if (actionHash.contains(res)) executeAction(actionHash[ res ], fileItem); } void DiskUsage::executeAction(int action, File * fileItem) { // check out the user's option switch (action) { case DELETE_ID: if (fileItem) del(fileItem); break; case EXCLUDE_ID: if (fileItem) exclude(fileItem); break; case PARENT_DIR_ID: dirUp(); break; case NEW_SEARCH_ID: emit newSearch(); break; case REFRESH_ID: load(baseURL); break; case INCLUDE_ALL_ID: includeAll(); break; case STEP_INTO_ID: { QString uri; if (fileItem && fileItem->isDir()) uri = fileItem->fullPath(); else uri = currentDirectory->fullPath(); ACTIVE_FUNC->openUrl(QUrl::fromLocalFile(uri)); } break; case LINES_VIEW_ID: setView(VIEW_LINES); break; case DETAILED_VIEW_ID: setView(VIEW_DETAILED); break; case FILELIGHT_VIEW_ID: setView(VIEW_FILELIGHT); break; case NEXT_VIEW_ID: setView((activeView + 1) % 3); break; case PREVIOUS_VIEW_ID: setView((activeView + 2) % 3); break; } // currentWidget()->setFocus(); } void DiskUsage::keyPressEvent(QKeyEvent *e) { if (activeView != VIEW_LOADER) { switch (e->key()) { case Qt::Key_E: if (e->modifiers() == Qt::ControlModifier) { executeAction(EXCLUDE_ID, getCurrentFile()); return; } break; case Qt::Key_D: if (e->modifiers() == Qt::ControlModifier) { executeAction(DETAILED_VIEW_ID); return; } break; case Qt::Key_F: if (e->modifiers() == Qt::ControlModifier) { executeAction(FILELIGHT_VIEW_ID); return; } break; case Qt::Key_I: if (e->modifiers() == Qt::ControlModifier) { executeAction(INCLUDE_ALL_ID); return; } break; case Qt::Key_L: if (e->modifiers() == Qt::ControlModifier) { executeAction(LINES_VIEW_ID); return; } break; case Qt::Key_N: if (e->modifiers() == Qt::ControlModifier) { executeAction(NEW_SEARCH_ID); return; } break; case Qt::Key_R: if (e->modifiers() == Qt::ControlModifier) { executeAction(REFRESH_ID); return; } break; case Qt::Key_Up: if (e->modifiers() == Qt::ShiftModifier) { executeAction(PARENT_DIR_ID); return; } break; case Qt::Key_Down: if (e->modifiers() == Qt::ShiftModifier) { executeAction(STEP_INTO_ID); return; } break; case Qt::Key_Left: if (e->modifiers() == Qt::ShiftModifier) { executeAction(PREVIOUS_VIEW_ID); return; } break; case Qt::Key_Right: if (e->modifiers() == Qt::ShiftModifier) { executeAction(NEXT_VIEW_ID); return; } break; case Qt::Key_Delete: if (!e->modifiers()) { executeAction(DELETE_ID, getCurrentFile()); return; } break; case Qt::Key_Plus: if (activeView == VIEW_FILELIGHT) { filelightView->zoomIn(); return; } break; case Qt::Key_Minus: if (activeView == VIEW_FILELIGHT) { filelightView->zoomOut(); return; } break; } } QStackedWidget::keyPressEvent(e); } QPixmap DiskUsage::getIcon(QString mime) { QPixmap icon; if (!QPixmapCache::find(mime, icon)) { // get the icon. if (mime == "Broken Link !") // FIXME: this doesn't work anymore - the reported mimetype for a broken link is now "unknown" icon = FL_LOADICON("file-broken"); else { QMimeDatabase db; QMimeType mt = db.mimeTypeForName(mime); if (mt.isValid()) icon = FL_LOADICON(mt.iconName()); else icon = FL_LOADICON("file-broken"); } // insert it into the cache QPixmapCache::insert(mime, icon); } return icon; } int DiskUsage::calculatePercents(bool emitSig, Directory *dirEntry, int depth) { int changeNr = 0; if (dirEntry == 0) dirEntry = root; for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) { File *item = *it; if (!item->isExcluded()) { int newPerc; if (dirEntry->size() == 0 && item->size() == 0) newPerc = 0; else if (dirEntry->size() == 0) newPerc = -1; else newPerc = (int)((double)item->size() / (double)currentSize * 10000. + 0.5); int oldPerc = item->intPercent(); item->setPercent(newPerc); if (emitSig && newPerc != oldPerc) { emit changed(item); changeNr++; } if (item->isDir()) changeNr += calculatePercents(emitSig, dynamic_cast(item), depth + 1); } } if (depth == 0 && changeNr != 0) emit changeFinished(); return changeNr; } QString DiskUsage::getToolTip(File *item) { QMimeDatabase db; QMimeType mt = db.mimeTypeForName(item->mime()); QString mime; if (mt.isValid()) mime = mt.comment(); time_t tma = item->time(); struct tm* t = localtime((time_t *) & tma); QDateTime tmp(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), QTime(t->tm_hour, t->tm_min)); QString date = QLocale().toString(tmp, QLocale::ShortFormat); QString str = "
" + "" + ""; if (item->isDir()) str += ""; str += "" + "" + "" + "
" + i18n("Name:") + "" + item->name() + "
" + i18n("Type:") + "" + mime + "
" + i18n("Size:") + "" + KRpermHandler::parseSize(item->size()) + "
" + i18n("Own size:") + "" + KRpermHandler::parseSize(item->ownSize()) + "
" + i18n("Last modified:") + "" + date + "
" + i18n("Permissions:") + "" + item->perm() + "
" + i18n("Owner:") + "" + item->owner() + " - " + item->group() + "
"; str.replace(' ', " "); return str; } void DiskUsage::setView(int view) { switch (view) { case VIEW_LINES: setCurrentWidget(lineView); break; case VIEW_DETAILED: setCurrentWidget(listView); break; case VIEW_FILELIGHT: setCurrentWidget(filelightView); break; case VIEW_LOADER: setCurrentWidget(loaderView); break; } // currentWidget()->setFocus(); emit viewChanged(activeView = view); } File * DiskUsage::getCurrentFile() { File * file = 0; switch (activeView) { case VIEW_LINES: file = lineView->getCurrentFile(); break; case VIEW_DETAILED: file = listView->getCurrentFile(); break; case VIEW_FILELIGHT: file = filelightView->getCurrentFile(); break; } return file; } bool DiskUsage::event(QEvent * e) { if (deleting) { // if we are deleting, disable the mouse and switch (e->type()) { // keyboard events case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: case QEvent::KeyPress: case QEvent::KeyRelease: return true; default: break; } } if (e->type() == QEvent::ShortcutOverride) { QKeyEvent* ke = (QKeyEvent*) e; if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::KeypadModifier) { switch (ke->key()) { case Qt::Key_Delete: case Qt::Key_Plus: case Qt::Key_Minus: ke->accept(); break; } } else if (ke->modifiers() == Qt::ShiftModifier) { switch (ke->key()) { case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: ke->accept(); break; } } else if (ke->modifiers() & Qt::ControlModifier) { switch (ke->key()) { case Qt::Key_D: case Qt::Key_E: case Qt::Key_F: case Qt::Key_I: case Qt::Key_L: case Qt::Key_N: case Qt::Key_R: ke->accept(); break; } } } return QStackedWidget::event(e); } diff --git a/krusader/DiskUsage/diskusage.h b/krusader/DiskUsage/diskusage.h index b389d6e5..14e1b279 100644 --- a/krusader/DiskUsage/diskusage.h +++ b/krusader/DiskUsage/diskusage.h @@ -1,219 +1,209 @@ -/*************************************************************************** - diskusage.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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(QString path); QString getConfigGroup() { return configGroup; } void * getProperty(File *, QString); void addProperty(File *, QString, void *); void removeProperty(File *, 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, QString = QString()); void changeDirectory(Directory *dir); Directory* getCurrentDir(); File* getCurrentFile(); QPixmap getIcon(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; 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.cpp b/krusader/DiskUsage/diskusagegui.cpp index 0024328b..35024713 100644 --- a/krusader/DiskUsage/diskusagegui.cpp +++ b/krusader/DiskUsage/diskusagegui.cpp @@ -1,253 +1,243 @@ -/*************************************************************************** - diskusagegui.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "diskusagegui.h" // QtCore #include // QtGui #include // QtWidgets #include #include #include #include #include #include #include #include "../kicons.h" #include "../krglobal.h" #include "../FileSystem/filesystem.h" #include "../Dialogs/krdialogs.h" DiskUsageGUI::DiskUsageGUI(const QUrl &openDir) : QDialog(nullptr), exitAtFailure(true) { setWindowTitle(i18n("Krusader::Disk Usage")); setAttribute(Qt::WA_DeleteOnClose); baseDirectory = openDir; QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); QGridLayout *duGrid = new QGridLayout(); duGrid->setSpacing(6); duGrid->setContentsMargins(11, 11, 11, 11); QWidget *duTools = new QWidget(this); QHBoxLayout *duHBox = new QHBoxLayout(duTools); duHBox->setContentsMargins(0, 0, 0, 0); duTools->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); btnNewSearch = new QToolButton(duTools); btnNewSearch->setIcon(QIcon(krLoader->loadIcon("document-open", KIconLoader::Desktop))); duHBox->addWidget(btnNewSearch); btnNewSearch->setToolTip(i18n("Start new disk usage search")); btnRefresh = new QToolButton(duTools); btnRefresh->setIcon(QIcon(krLoader->loadIcon("view-refresh", KIconLoader::Desktop))); duHBox->addWidget(btnRefresh); btnRefresh->setToolTip(i18n("Refresh")); btnDirUp = new QToolButton(duTools); btnDirUp->setIcon(QIcon(krLoader->loadIcon("go-up", KIconLoader::Desktop))); duHBox->addWidget(btnDirUp); btnDirUp->setToolTip(i18n("Parent folder")); QWidget *separatorWidget = new QWidget(duTools); separatorWidget->setMinimumWidth(10); duHBox->addWidget(separatorWidget); btnLines = new QToolButton(duTools); btnLines->setIcon(QIcon(krLoader->loadIcon("view-list-details", KIconLoader::Desktop))); btnLines->setCheckable(true); duHBox->addWidget(btnLines); btnLines->setToolTip(i18n("Line view")); btnDetailed = new QToolButton(duTools); btnDetailed->setIcon(QIcon(krLoader->loadIcon("view-list-tree", KIconLoader::Desktop))); btnDetailed->setCheckable(true); duHBox->addWidget(btnDetailed); btnDetailed->setToolTip(i18n("Detailed view")); btnFilelight = new QToolButton(duTools); btnFilelight->setIcon(QIcon(krLoader->loadIcon("kr_diskusage", KIconLoader::Desktop))); btnFilelight->setCheckable(true); duHBox->addWidget(btnFilelight); btnFilelight->setToolTip(i18n("Filelight view")); QWidget *spacerWidget = new QWidget(duTools); duHBox->addWidget(spacerWidget); QHBoxLayout *hboxlayout = new QHBoxLayout(spacerWidget); QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed); hboxlayout->addItem(spacer); duGrid->addWidget(duTools, 0, 0); diskUsage = new DiskUsage("DiskUsage", this); duGrid->addWidget(diskUsage, 1, 0); status = new KSqueezedTextLabel(this); duGrid->addWidget(status, 2, 0); mainLayout->addLayout(duGrid); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); mainLayout->addWidget(buttonBox); connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); connect(diskUsage, SIGNAL(status(QString)), this, SLOT(slotStatus(QString))); connect(diskUsage, SIGNAL(viewChanged(int)), this, SLOT(slotViewChanged(int))); connect(diskUsage, SIGNAL(newSearch()), this, SLOT(askDir())); connect(diskUsage, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool))); connect(btnNewSearch, SIGNAL(clicked()), this, SLOT(askDir())); connect(btnRefresh, SIGNAL(clicked()), this, SLOT(slotLoadUsageInfo())); connect(btnDirUp, SIGNAL(clicked()), diskUsage, SLOT(dirUp())); connect(btnLines, SIGNAL(clicked()), this, SLOT(slotSelectLinesView())); connect(btnDetailed, SIGNAL(clicked()), this, SLOT(slotSelectListView())); connect(btnFilelight, SIGNAL(clicked()), this, SLOT(slotSelectFilelightView())); KConfigGroup group(krConfig, "DiskUsage"); int view = group.readEntry("View", VIEW_LINES); if (view < VIEW_LINES || view > VIEW_FILELIGHT) view = VIEW_LINES; diskUsage->setView(view); sizeX = group.readEntry("Window Width", QFontMetrics(font()).width("W") * 70); sizeY = group.readEntry("Window Height", QFontMetrics(font()).height() * 25); resize(sizeX, sizeY); if (group.readEntry("Window Maximized", false)) { setWindowState(windowState() | Qt::WindowMaximized); } } void DiskUsageGUI::askDirAndShow() { if (askDir()) { show(); } } void DiskUsageGUI::slotLoadFinished(bool result) { if (exitAtFailure && !result) { close(); } else { exitAtFailure = false; } } void DiskUsageGUI::enableButtons(bool isOn) { btnNewSearch->setEnabled(isOn); btnRefresh->setEnabled(isOn); btnDirUp->setEnabled(isOn); btnLines->setEnabled(isOn); btnDetailed->setEnabled(isOn); btnFilelight->setEnabled(isOn); } void DiskUsageGUI::resizeEvent(QResizeEvent *e) { if (!isMaximized()) { sizeX = e->size().width(); sizeY = e->size().height(); } QDialog::resizeEvent(e); } void DiskUsageGUI::closeEvent(QCloseEvent *event) { KConfigGroup group(krConfig, "DiskUsage"); group.writeEntry("Window Width", sizeX); group.writeEntry("Window Height", sizeY); group.writeEntry("Window Maximized", isMaximized()); group.writeEntry("View", diskUsage->getActiveView()); event->accept(); } void DiskUsageGUI::slotLoadUsageInfo() { diskUsage->load(baseDirectory); } void DiskUsageGUI::slotStatus(QString stat) { status->setText(stat); } void DiskUsageGUI::slotViewChanged(int view) { if (view == VIEW_LOADER) { enableButtons(false); return; } enableButtons(true); btnLines->setChecked(false); btnDetailed->setChecked(false); btnFilelight->setChecked(false); switch (view) { case VIEW_LINES: btnLines->setChecked(true); break; case VIEW_DETAILED: btnDetailed->setChecked(true); break; case VIEW_FILELIGHT: btnFilelight->setChecked(true); break; case VIEW_LOADER: break; } } bool DiskUsageGUI::askDir() { // ask the user for the copy destX const QUrl newDir = KChooseDir::getDir(i18n("Viewing the usage of folder:"), baseDirectory, baseDirectory); if (newDir.isEmpty()) return false; baseDirectory = newDir; QTimer::singleShot(0, this, SLOT(slotLoadUsageInfo())); return true; } diff --git a/krusader/DiskUsage/diskusagegui.h b/krusader/DiskUsage/diskusagegui.h index bd150500..268f77e4 100644 --- a/krusader/DiskUsage/diskusagegui.h +++ b/krusader/DiskUsage/diskusagegui.h @@ -1,97 +1,87 @@ -/*************************************************************************** - diskusagegui.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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() {} void askDirAndShow(); protected slots: virtual void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; protected: virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; private slots: bool askDir(); void slotLoadUsageInfo(); void slotStatus(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.cpp b/krusader/DiskUsage/dufilelight.cpp index 1391a5d7..c762d33c 100644 --- a/krusader/DiskUsage/dufilelight.cpp +++ b/krusader/DiskUsage/dufilelight.cpp @@ -1,235 +1,225 @@ -/*************************************************************************** - dufilelight.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "dufilelight.h" #include "radialMap/radialMap.h" // QtGui #include #include // QtWidgets #include #include #include #define SCHEME_POPUP_ID 6730 DUFilelight::DUFilelight(DiskUsage *usage) : RadialMap::Widget(usage), diskUsage(usage), currentDir(0), refreshNeeded(true) { // setFocusPolicy(Qt::StrongFocus); connect(diskUsage, SIGNAL(enteringDirectory(Directory*)), this, SLOT(slotDirChanged(Directory*))); connect(diskUsage, SIGNAL(clearing()), this, SLOT(clear())); connect(diskUsage, SIGNAL(changed(File*)), this, SLOT(slotChanged(File*))); connect(diskUsage, SIGNAL(deleted(File*)), this, SLOT(slotChanged(File*))); connect(diskUsage, SIGNAL(changeFinished()), this, SLOT(slotRefresh())); connect(diskUsage, SIGNAL(deleteFinished()), this, SLOT(slotRefresh())); connect(diskUsage, SIGNAL(currentChanged(int)), this, SLOT(slotAboutToShow(int))); } void DUFilelight::slotDirChanged(Directory *dir) { if (diskUsage->currentWidget() != this) return; if (currentDir != dir) { currentDir = dir; invalidate(false); create(dir); refreshNeeded = false; } } void DUFilelight::clear() { invalidate(false); currentDir = 0; } File * DUFilelight::getCurrentFile() { const RadialMap::Segment * focus = focusSegment(); if (!focus || focus->isFake() || focus->file() == currentDir) return 0; return (File *)focus->file(); } void DUFilelight::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) { File * file = 0; const RadialMap::Segment * focus = focusSegment(); if (focus && !focus->isFake() && focus->file() != currentDir) file = (File *)focus->file(); QMenu filelightPopup; filelightPopup.addAction(i18n("Zoom In"), this, SLOT(zoomIn()), Qt::Key_Plus); filelightPopup.addAction(i18n("Zoom Out"), this, SLOT(zoomOut()), Qt::Key_Minus); QMenu schemePopup; schemePopup.addAction(i18n("Rainbow"), this, SLOT(schemeRainbow())); schemePopup.addAction(i18n("High Contrast"), this, SLOT(schemeHighContrast())); schemePopup.addAction(i18n("KDE"), this, SLOT(schemeKDE())); filelightPopup.addMenu(&schemePopup); schemePopup.setTitle(i18n("Scheme")); filelightPopup.addAction(i18n("Increase contrast"), this, SLOT(increaseContrast())); filelightPopup.addAction(i18n("Decrease contrast"), this, SLOT(decreaseContrast())); QAction * act = filelightPopup.addAction(i18n("Use anti-aliasing"), this, SLOT(changeAntiAlias())); act->setCheckable(true); act->setChecked(Filelight::Config::antiAliasFactor > 1); act = filelightPopup.addAction(i18n("Show small files"), this, SLOT(showSmallFiles())); act->setCheckable(true); act->setChecked(Filelight::Config::showSmallFiles); act = filelightPopup.addAction(i18n("Vary label font sizes"), this, SLOT(varyLabelFontSizes())); act->setCheckable(true); act->setChecked(Filelight::Config::varyLabelFontSizes); filelightPopup.addAction(i18n("Minimum font size"), this, SLOT(minFontSize())); diskUsage->rightClickMenu(event->globalPos(), file, &filelightPopup, i18n("Filelight")); return; } else if (event->button() == Qt::LeftButton) { const RadialMap::Segment * focus = focusSegment(); if (focus && !focus->isFake() && focus->file() == currentDir) { diskUsage->dirUp(); return; } else if (focus && !focus->isFake() && focus->file()->isDir()) { diskUsage->changeDirectory((Directory *)focus->file()); return; } } RadialMap::Widget::mousePressEvent(event); } void DUFilelight::setScheme(Filelight::MapScheme scheme) { Filelight::Config::scheme = scheme; Filelight::Config::write(); slotRefresh(); } void DUFilelight::increaseContrast() { if ((Filelight::Config::contrast += 10) > 100) Filelight::Config::contrast = 100; Filelight::Config::write(); slotRefresh(); } void DUFilelight::decreaseContrast() { if ((Filelight::Config::contrast -= 10) > 100) Filelight::Config::contrast = 0; Filelight::Config::write(); slotRefresh(); } void DUFilelight::changeAntiAlias() { Filelight::Config::antiAliasFactor = 1 + (Filelight::Config::antiAliasFactor == 1); Filelight::Config::write(); slotRefresh(); } void DUFilelight::showSmallFiles() { Filelight::Config::showSmallFiles = !Filelight::Config::showSmallFiles; Filelight::Config::write(); slotRefresh(); } void DUFilelight::varyLabelFontSizes() { Filelight::Config::varyLabelFontSizes = !Filelight::Config::varyLabelFontSizes; Filelight::Config::write(); slotRefresh(); } void DUFilelight::minFontSize() { bool ok = false; int result = QInputDialog::getInt(this, i18n("Krusader::Filelight"), i18n("Minimum font size"), (int)Filelight::Config::minFontPitch, 1, 100, 1, &ok); if (ok) { Filelight::Config::minFontPitch = (uint)result; Filelight::Config::write(); slotRefresh(); } } void DUFilelight::slotAboutToShow(int ndx) { QWidget *widget = diskUsage->widget(ndx); if (widget == this && (diskUsage->getCurrentDir() != currentDir || refreshNeeded)) { refreshNeeded = false; if ((currentDir = diskUsage->getCurrentDir()) != 0) { invalidate(false); create(currentDir); } } } void DUFilelight::slotRefresh() { if (diskUsage->currentWidget() != this) return; refreshNeeded = false; if (currentDir && currentDir == diskUsage->getCurrentDir()) { invalidate(false); create(currentDir); } } void DUFilelight::slotChanged(File *) { if (!refreshNeeded) refreshNeeded = true; } diff --git a/krusader/DiskUsage/dufilelight.h b/krusader/DiskUsage/dufilelight.h index c9bd7a0b..c3cb7068 100644 --- a/krusader/DiskUsage/dufilelight.h +++ b/krusader/DiskUsage/dufilelight.h @@ -1,89 +1,79 @@ -/*************************************************************************** - dufilelight.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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: virtual void mousePressEvent(QMouseEvent*) Q_DECL_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 79c96667..94ad7d4f 100644 --- a/krusader/DiskUsage/dulines.cpp +++ b/krusader/DiskUsage/dulines.cpp @@ -1,544 +1,534 @@ -/*************************************************************************** - dulines.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "dulines.h" #include "../kicons.h" #include "../krglobal.h" #include "../FileSystem/krpermhandler.h" // QtCore #include // QtGui #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include class DULinesItemDelegate : public QItemDelegate { public: explicit DULinesItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {} virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE { QItemDelegate::paint(painter, option, index); QVariant value = index.data(Qt::UserRole); if (value.isValid()) { QString text = value.toString(); value = index.data(Qt::DisplayRole); QString display; if (value.isValid()) display = value.toString(); QSize iconSize; value = index.data(Qt::DecorationRole); if (value.isValid()) iconSize = qvariant_cast(value).actualSize(option.decorationSize); painter->save(); painter->setClipRect(option.rect); QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) cg = QPalette::Inactive; if (option.state & QStyle::State_Selected) { painter->setPen(option.palette.color(cg, QPalette::HighlightedText)); } else { painter->setPen(option.palette.color(cg, QPalette::Text)); } QFont fnt = option.font; fnt.setItalic(true); painter->setFont(fnt); QFontMetrics fm(fnt); QString renderedText = text; int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin); int pos = 3 * textMargin + option.fontMetrics.width(display) + iconSize.width(); bool truncd = false; QRect rct = option.rect; if (rct.width() > pos) { rct.setX(rct.x() + pos); if (fm.width(renderedText) > rct.width()) { truncd = true; int points = fm.width("..."); while (!renderedText.isEmpty() && (fm.width(renderedText) + points > rct.width())) renderedText.truncate(renderedText.length() - 1); renderedText += "..."; } painter->drawText(rct, Qt::AlignLeft, renderedText); } else truncd = true; if (truncd) ((QAbstractItemModel *)index.model())->setData(index, QVariant(display + " " + text), Qt::ToolTipRole); else ((QAbstractItemModel *)index.model())->setData(index, QVariant(), Qt::ToolTipRole); painter->restore(); } } }; class DULinesItem : public QTreeWidgetItem { public: DULinesItem(DiskUsage *diskUsageIn, File *fileItem, QTreeWidget * parent, QString label1, QString label2, QString label3) : QTreeWidgetItem(parent), diskUsage(diskUsageIn), file(fileItem) { setText(0, label1); setText(1, label2); setText(2, label3); setTextAlignment(1, Qt::AlignRight); } DULinesItem(DiskUsage *diskUsageIn, File *fileItem, QTreeWidget * parent, QTreeWidgetItem * after, QString label1, QString label2, QString label3) : QTreeWidgetItem(parent, after), diskUsage(diskUsageIn), file(fileItem) { setText(0, label1); setText(1, label2); setText(2, label3); setTextAlignment(1, Qt::AlignRight); } virtual bool operator<(const QTreeWidgetItem &other) const Q_DECL_OVERRIDE { int column = treeWidget() ? treeWidget()->sortColumn() : 0; if (text(0) == "..") return true; const DULinesItem *compWith = dynamic_cast< const DULinesItem * >(&other); if (compWith == 0) return false; switch (column) { case 0: case 1: return file->size() > compWith->file->size(); default: return text(column) < other.text(column); } } inline File * getFile() { return file; } private: DiskUsage *diskUsage; File *file; }; DULines::DULines(DiskUsage *usage) : KrTreeWidget(usage), diskUsage(usage), refreshNeeded(false), started(false) { setItemDelegate(itemDelegate = new DULinesItemDelegate()); setAllColumnsShowFocus(true); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setIndentation(10); int defaultSize = QFontMetrics(font()).width("W"); QStringList labels; labels << i18n("Line View"); labels << i18n("Percent"); labels << i18n("Name"); setHeaderLabels(labels); header()->setSectionResizeMode(QHeaderView::Interactive); KConfigGroup group(krConfig, diskUsage->getConfigGroup()); showFileSize = group.readEntry("L Show File Size", true); if (group.hasKey("L State")) header()->restoreState(group.readEntry("L State", QByteArray())); else { setColumnWidth(0, defaultSize * 20); setColumnWidth(1, defaultSize * 6); setColumnWidth(2, defaultSize * 20); } setStretchingColumn(0); header()->setSortIndicatorShown(true); sortItems(1, Qt::AscendingOrder); // toolTip = new DULinesToolTip( diskUsage, viewport(), this ); connect(diskUsage, SIGNAL(enteringDirectory(Directory*)), this, SLOT(slotDirChanged(Directory*))); connect(diskUsage, SIGNAL(clearing()), this, SLOT(clear())); connect(header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(sectionResized(int))); connect(this, SIGNAL(itemRightClicked(QTreeWidgetItem*,QPoint,int)), this, SLOT(slotRightClicked(QTreeWidgetItem*,QPoint))); connect(diskUsage, SIGNAL(changed(File*)), this, SLOT(slotChanged(File*))); connect(diskUsage, SIGNAL(deleted(File*)), this, SLOT(slotDeleted(File*))); started = true; } DULines::~DULines() { KConfigGroup group(krConfig, diskUsage->getConfigGroup()); group.writeEntry("L State", header()->saveState()); delete itemDelegate; } bool DULines::event(QEvent * event) { switch (event->type()) { case QEvent::ToolTip: { QHelpEvent *he = static_cast(event); if (viewport()) { QPoint pos = viewport()->mapFromGlobal(he->globalPos()); QTreeWidgetItem * item = itemAt(pos); int column = columnAt(pos.x()); if (item && column == 1) { File *fileItem = ((DULinesItem *)item)->getFile(); QToolTip::showText(he->globalPos(), diskUsage->getToolTip(fileItem), this); return true; } } } break; default: break; } return KrTreeWidget::event(event); } void DULines::slotDirChanged(Directory *dirEntry) { clear(); QTreeWidgetItem * lastItem = 0; if (!(dirEntry->parent() == 0)) { lastItem = new QTreeWidgetItem(this); lastItem->setText(0, ".."); lastItem->setIcon(0, FL_LOADICON("go-up")); lastItem->setFlags(lastItem->flags() & (~Qt::ItemIsSelectable)); } int maxPercent = -1; for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) { File *item = *it; if (!item->isExcluded() && item->intPercent() > maxPercent) maxPercent = item->intPercent(); } for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) { File *item = *it; QString fileName = item->name(); if (lastItem == 0) lastItem = new DULinesItem(diskUsage, item, this, "", item->percent() + " ", fileName); else lastItem = new DULinesItem(diskUsage, item, this, lastItem, "", item->percent() + " ", fileName); if (item->isExcluded()) lastItem->setHidden(true); int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; lastItem->setIcon(2, diskUsage->getIcon(item->mime())); lastItem->setData(0, Qt::DecorationRole, createPixmap(item->intPercent(), maxPercent, header()->sectionSize(0) - 2 * textMargin)); if (showFileSize) lastItem->setData(2, Qt::UserRole, " [" + KIO::convertSize(item->size()) + ']'); QSize size = lastItem->sizeHint(0); size.setWidth(16); lastItem->setSizeHint(0, size); } if (topLevelItemCount() > 0) { setCurrentItem(topLevelItem(0)); } } QPixmap DULines::createPixmap(int percent, int maxPercent, int maxWidth) { if (percent < 0 || percent > maxPercent || maxWidth < 2 || maxPercent == 0) return QPixmap(); maxWidth -= 2; int actualWidth = maxWidth * percent / maxPercent; if (actualWidth == 0) return QPixmap(); QPen pen; pen.setColor(Qt::black); QPainter painter; int size = QFontMetrics(font()).height() - 2; QRect rect(0, 0, actualWidth, size); QRect frameRect(0, 0, actualWidth - 1, size - 1); QPixmap pixmap(rect.width(), rect.height()); painter.begin(&pixmap); painter.setPen(pen); for (int i = 1; i < actualWidth - 1; i++) { int color = (511 * i / (maxWidth - 1)); if (color < 256) pen.setColor(QColor(255 - color, 255, 0)); else pen.setColor(QColor(color - 256, 511 - color, 0)); painter.setPen(pen); painter.drawLine(i, 1, i, size - 1); } pen.setColor(Qt::black); painter.setPen(pen); if (actualWidth != 1) painter.drawRect(frameRect); else painter.drawLine(0, 0, 0, size); painter.end(); pixmap.detach(); return pixmap; } void DULines::resizeEvent(QResizeEvent * re) { KrTreeWidget::resizeEvent(re); if (started && (re->oldSize() != re->size())) sectionResized(0); } void DULines::sectionResized(int column) { if (topLevelItemCount() == 0 || column != 0) return; Directory * currentDir = diskUsage->getCurrentDir(); if (currentDir == 0) return; int maxPercent = -1; for (Iterator it = currentDir->iterator(); it != currentDir->end(); ++it) { File *item = *it; if (!item->isExcluded() && item->intPercent() > maxPercent) maxPercent = item->intPercent(); } QTreeWidgetItemIterator it2(this); while (*it2) { QTreeWidgetItem *lvitem = *it2; if (lvitem->text(0) != "..") { DULinesItem *duItem = dynamic_cast< DULinesItem *>(lvitem); if (duItem) { int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; duItem->setData(0, Qt::DecorationRole, createPixmap(duItem->getFile()->intPercent(), maxPercent, header()->sectionSize(0) - 2 * textMargin)); QSize size = duItem->sizeHint(0); size.setWidth(16); duItem->setSizeHint(0, size); } } it2++; } } bool DULines::doubleClicked(QTreeWidgetItem * item) { if (item) { if (item->text(0) != "..") { File *fileItem = ((DULinesItem *)item)->getFile(); if (fileItem->isDir()) diskUsage->changeDirectory(dynamic_cast(fileItem)); return true; } else { Directory *upDir = (Directory *)diskUsage->getCurrentDir()->parent(); if (upDir) diskUsage->changeDirectory(upDir); return true; } } return false; } void DULines::mouseDoubleClickEvent(QMouseEvent * e) { if (e || e->button() == Qt::LeftButton) { QPoint vp = viewport()->mapFromGlobal(e->globalPos()); QTreeWidgetItem * item = itemAt(vp); if (doubleClicked(item)) return; } KrTreeWidget::mouseDoubleClickEvent(e); } void DULines::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Return : case Qt::Key_Enter : if (doubleClicked(currentItem())) return; break; case Qt::Key_Left : case Qt::Key_Right : case Qt::Key_Up : case Qt::Key_Down : if (e->modifiers() == Qt::ShiftModifier) { e->ignore(); return; } break; case Qt::Key_Delete : e->ignore(); return; } KrTreeWidget::keyPressEvent(e); } void DULines::slotRightClicked(QTreeWidgetItem *item, const QPoint &pos) { File * file = 0; if (item && item->text(0) != "..") file = ((DULinesItem *)item)->getFile(); QMenu linesPopup; QAction *act = linesPopup.addAction(i18n("Show file sizes"), this, SLOT(slotShowFileSizes())); act->setChecked(showFileSize); diskUsage->rightClickMenu(pos, file, &linesPopup, i18n("Lines")); } void DULines::slotShowFileSizes() { showFileSize = !showFileSize; slotDirChanged(diskUsage->getCurrentDir()); } File * DULines::getCurrentFile() { QTreeWidgetItem *item = currentItem(); if (item == 0 || item->text(0) == "..") return 0; return ((DULinesItem *)item)->getFile(); } void DULines::slotChanged(File * item) { QTreeWidgetItemIterator it(this); while (*it) { QTreeWidgetItem *lvitem = *it; it++; if (lvitem->text(0) != "..") { DULinesItem *duItem = (DULinesItem *)(lvitem); if (duItem->getFile() == item) { setSortingEnabled(false); duItem->setHidden(item->isExcluded()); duItem->setText(1, item->percent()); if (!refreshNeeded) { refreshNeeded = true; QTimer::singleShot(0, this, SLOT(slotRefresh())); } break; } } } } void DULines::slotDeleted(File * item) { QTreeWidgetItemIterator it(this); while (*it) { QTreeWidgetItem *lvitem = *it; it++; if (lvitem->text(0) != "..") { DULinesItem *duItem = (DULinesItem *)(lvitem); if (duItem->getFile() == item) { delete duItem; break; } } } } void DULines::slotRefresh() { if (refreshNeeded) { refreshNeeded = false; setSortingEnabled(true); sortItems(1, Qt::AscendingOrder); } } diff --git a/krusader/DiskUsage/dulines.h b/krusader/DiskUsage/dulines.h index a444d307..f5df71e8 100644 --- a/krusader/DiskUsage/dulines.h +++ b/krusader/DiskUsage/dulines.h @@ -1,88 +1,78 @@ -/*************************************************************************** - dulines.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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(); 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; virtual bool event(QEvent * event) Q_DECL_OVERRIDE; virtual void mouseDoubleClickEvent(QMouseEvent * e) Q_DECL_OVERRIDE; virtual void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; virtual void resizeEvent(QResizeEvent *) Q_DECL_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.cpp b/krusader/DiskUsage/dulistview.cpp index 1f5f2dfc..0add3bb9 100644 --- a/krusader/DiskUsage/dulistview.cpp +++ b/krusader/DiskUsage/dulistview.cpp @@ -1,283 +1,273 @@ -/*************************************************************************** - dulistview.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "dulistview.h" #include "../krglobal.h" #include "../kicons.h" #include "../FileSystem/krpermhandler.h" // QtCore #include #include // QtGui #include #include #include // QtWidgets #include #include #include DUListView::DUListView(DiskUsage *usage) : KrTreeWidget(usage), diskUsage(usage) { setAllColumnsShowFocus(true); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setRootIsDecorated(true); setIndentation(10); setItemsExpandable(true); QStringList labels; labels << i18n("Name"); labels << i18n("Percent"); labels << i18n("Total size"); labels << i18n("Own size"); labels << i18n("Type"); labels << i18n("Date"); labels << i18n("Permissions"); labels << i18n("Owner"); labels << i18n("Group"); setHeaderLabels(labels); header()->setSectionResizeMode(QHeaderView::Interactive); KConfigGroup group(krConfig, diskUsage->getConfigGroup()); if (group.hasKey("D State")) header()->restoreState(group.readEntry("D State", QByteArray())); else { int defaultSize = QFontMetrics(font()).width("W"); setColumnWidth(0, defaultSize * 20); setColumnWidth(1, defaultSize * 5); setColumnWidth(2, defaultSize * 10); setColumnWidth(3, defaultSize * 10); setColumnWidth(4, defaultSize * 10); setColumnWidth(5, defaultSize * 10); setColumnWidth(6, defaultSize * 6); setColumnWidth(7, defaultSize * 5); setColumnWidth(8, defaultSize * 5); } header()->setSortIndicatorShown(true); sortItems(2, Qt::AscendingOrder); connect(diskUsage, SIGNAL(enteringDirectory(Directory*)), this, SLOT(slotDirChanged(Directory*))); connect(diskUsage, SIGNAL(clearing()), this, SLOT(clear())); connect(diskUsage, SIGNAL(changed(File*)), this, SLOT(slotChanged(File*))); connect(diskUsage, SIGNAL(deleted(File*)), this, SLOT(slotDeleted(File*))); connect(this, SIGNAL(itemRightClicked(QTreeWidgetItem*,QPoint,int)), this, SLOT(slotRightClicked(QTreeWidgetItem*,QPoint))); connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(slotExpanded(QTreeWidgetItem*))); } DUListView::~ DUListView() { KConfigGroup group(krConfig, diskUsage->getConfigGroup()); group.writeEntry("D State", header()->saveState()); } void DUListView::addDirectory(Directory *dirEntry, QTreeWidgetItem *parent) { QTreeWidgetItem * lastItem = 0; if (parent == 0 && !(dirEntry->parent() == 0)) { lastItem = new QTreeWidgetItem(this); lastItem->setText(0, ".."); lastItem->setIcon(0, FL_LOADICON("go-up")); lastItem->setFlags(Qt::ItemIsEnabled); } for (Iterator it = dirEntry->iterator(); it != dirEntry->end(); ++it) { File *item = *it; QMimeDatabase db; QMimeType mt = db.mimeTypeForName(item->mime()); QString mime; if (mt.isValid()) mime = mt.comment(); time_t tma = item->time(); struct tm* t = localtime((time_t *) & tma); QDateTime tmp(QDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday), QTime(t->tm_hour, t->tm_min)); QString date = QLocale().toString(tmp, QLocale::ShortFormat); QString totalSize = KRpermHandler::parseSize(item->size()) + ' '; QString ownSize = KRpermHandler::parseSize(item->ownSize()) + ' '; QString percent = item->percent(); if (lastItem == 0 && parent == 0) lastItem = new DUListViewItem(diskUsage, item, this, item->name(), percent, totalSize, ownSize, mime, date, item->perm(), item->owner(), item->group()); else if (lastItem == 0) lastItem = new DUListViewItem(diskUsage, item, parent, item->name(), percent, totalSize, ownSize, mime, date, item->perm(), item->owner(), item->group()); else if (parent == 0) lastItem = new DUListViewItem(diskUsage, item, this, lastItem, item->name(), percent, totalSize, ownSize, mime, date, item->perm(), item->owner(), item->group()); else lastItem = new DUListViewItem(diskUsage, item, parent, lastItem, item->name(), percent, totalSize, ownSize, mime, date, item->perm(), item->owner(), item->group()); if (item->isExcluded()) lastItem->setHidden(true); lastItem->setIcon(0, diskUsage->getIcon(item->mime())); if (item->isDir() && !item->isSymLink()) lastItem->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); } if (topLevelItemCount() > 0) { setCurrentItem(topLevelItem(0)); } } void DUListView::slotDirChanged(Directory *dirEntry) { clear(); addDirectory(dirEntry, 0); } File * DUListView::getCurrentFile() { QTreeWidgetItem *item = currentItem(); if (item == 0 || item->text(0) == "..") return 0; return ((DUListViewItem *)item)->getFile(); } void DUListView::slotChanged(File * item) { void * itemPtr = diskUsage->getProperty(item, "ListView-Ref"); if (itemPtr == 0) return; DUListViewItem *duItem = (DUListViewItem *)itemPtr; duItem->setHidden(item->isExcluded()); duItem->setText(1, item->percent()); duItem->setText(2, KRpermHandler::parseSize(item->size()) + ' '); duItem->setText(3, KRpermHandler::parseSize(item->ownSize()) + ' '); } void DUListView::slotDeleted(File * item) { void * itemPtr = diskUsage->getProperty(item, "ListView-Ref"); if (itemPtr == 0) return; DUListViewItem *duItem = (DUListViewItem *)itemPtr; delete duItem; } void DUListView::slotRightClicked(QTreeWidgetItem *item, const QPoint & pos) { File * file = 0; if (item && item->text(0) != "..") file = ((DUListViewItem *)item)->getFile(); diskUsage->rightClickMenu(pos, file); } bool DUListView::doubleClicked(QTreeWidgetItem * item) { if (item) { if (item->text(0) != "..") { File *fileItem = ((DUListViewItem *)item)->getFile(); if (fileItem->isDir()) diskUsage->changeDirectory(dynamic_cast(fileItem)); return true; } else { Directory *upDir = (Directory *)diskUsage->getCurrentDir()->parent(); if (upDir) diskUsage->changeDirectory(upDir); return true; } } return false; } void DUListView::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 DUListView::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 DUListView::slotExpanded(QTreeWidgetItem * item) { if (item == 0 || item->text(0) == "..") return; if (item->childCount() == 0) { File *fileItem = ((DUListViewItem *)item)->getFile(); if (fileItem->isDir()) addDirectory(dynamic_cast(fileItem), item); } } diff --git a/krusader/DiskUsage/dulistview.h b/krusader/DiskUsage/dulistview.h index 7df34d3b..16691a6e 100644 --- a/krusader/DiskUsage/dulistview.h +++ b/krusader/DiskUsage/dulistview.h @@ -1,194 +1,184 @@ -/*************************************************************************** - dulistview.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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, QString label1, QString label2, QString label3, QString label4, QString label5, QString label6, QString label7, QString label8, 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, QString label1, QString label2, QString label3, QString label4, QString label5, QString label6, QString label7, QString label8, 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, QString label1, QString label2, QString label3, QString label4, QString label5, QString label6, QString label7, QString label8, 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, QString label1, QString label2, QString label3, QString label4, QString label5, QString label6, QString label7, QString label8, 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->removeProperty(file, "ListView-Ref"); } virtual bool operator<(const QTreeWidgetItem &other) const Q_DECL_OVERRIDE { int column = treeWidget() ? treeWidget()->sortColumn() : 0; if (text(0) == "..") return true; const DUListViewItem *compWith = dynamic_cast< const DUListViewItem * >(&other); if (compWith == 0) 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(); File * getCurrentFile(); public slots: void slotDirChanged(Directory *); void slotChanged(File *); void slotDeleted(File *); void slotRightClicked(QTreeWidgetItem *, const QPoint &); void slotExpanded(QTreeWidgetItem *); protected: DiskUsage *diskUsage; virtual void mouseDoubleClickEvent(QMouseEvent * e) Q_DECL_OVERRIDE; virtual void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; private: void addDirectory(Directory *dirEntry, QTreeWidgetItem *parent); bool doubleClicked(QTreeWidgetItem * item); }; #endif /* __DU_LISTVIEW_H__ */ diff --git a/krusader/FileSystem/defaultfilesystem.cpp b/krusader/FileSystem/defaultfilesystem.cpp index b29bb727..c7e848c4 100644 --- a/krusader/FileSystem/defaultfilesystem.cpp +++ b/krusader/FileSystem/defaultfilesystem.cpp @@ -1,422 +1,412 @@ -/*************************************************************************** - defaultfilesystem.cpp - ------------------- - copyright : (C) 2000 by Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "defaultfilesystem.h" // QtCore #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fileitem.h" #include "../defaults.h" #include "../krglobal.h" #include "../krservices.h" #include "../JobMan/krjob.h" DefaultFileSystem::DefaultFileSystem(): FileSystem(), _watcher() { _type = FS_DEFAULT; } void DefaultFileSystem::copyFiles(const QList &urls, const QUrl &destination, KIO::CopyJob::CopyMode mode, bool showProgressInfo, JobMan::StartMode startMode) { // resolve relative path before resolving symlinks const QUrl dest = resolveRelativePath(destination); KIO::JobFlags flags = showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo; KrJob *krJob = KrJob::createCopyJob(mode, urls, dest, flags); // destination can be a full path with filename when copying/moving a single file const QUrl destDir = dest.adjusted(QUrl::RemoveFilename); connect(krJob, &KrJob::started, this, [=](KIO::Job *job) { connectJobToDestination(job, destDir); }); if (mode == KIO::CopyJob::Move) { // notify source about removed files connect(krJob, &KrJob::started, this, [=](KIO::Job *job) { connectJobToSources(job, urls); }); } krJobMan->manageJob(krJob, startMode); } void DefaultFileSystem::dropFiles(const QUrl &destination, QDropEvent *event) { qDebug() << "destination=" << destination; // resolve relative path before resolving symlinks const QUrl dest = resolveRelativePath(destination); KIO::DropJob *job = KIO::drop(event, dest); #if KIO_VERSION >= QT_VERSION_CHECK(5, 30, 0) // NOTE: a DropJob "starts" with showing a menu. If the operation is choosen (copy/move/link) // the actual CopyJob starts automatically - we cannot manage the start of the CopyJob (see // documentation for KrJob) connect(job, &KIO::DropJob::copyJobStarted, this, [=](KIO::CopyJob *kJob) { connectJobToDestination(job, dest); // now we have to refresh the destination KrJob *krJob = KrJob::createDropJob(job, kJob); krJobMan->manageStartedJob(krJob, kJob); if (kJob->operationMode() == KIO::CopyJob::Move) { // notify source about removed files connectJobToSources(kJob, kJob->srcUrls()); } }); #else // NOTE: DropJob does not provide information about the actual user choice // (move/copy/link/abort). We have to assume the worst (move) connectJobToDestination(job, dest); connectJobToSources(job, KUrlMimeData::urlsFromMimeData(event->mimeData())); #endif } void DefaultFileSystem::addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, const QString &dir) { QUrl destination(_currentDirectory); if (!dir.isEmpty()) { destination.setPath(QDir::cleanPath(destination.path() + '/' + dir)); const QString scheme = destination.scheme(); if (scheme == "tar" || scheme == "zip" || scheme == "krarc") { if (QDir(destination.path()).exists()) // if we get out from the archive change the protocol destination.setScheme("file"); } } destination = ensureTrailingSlash(destination); // destination is always a directory copyFiles(fileUrls, destination, mode); } void DefaultFileSystem::mkDir(const QString &name) { KJob *job; if (name.contains('/')) { job = KIO::mkpath(getUrl(name)); } else { job = KIO::mkdir(getUrl(name)); } connectJobToDestination(job, currentDirectory()); } void DefaultFileSystem::rename(const QString &oldName, const QString &newName) { const QUrl oldUrl = getUrl(oldName); const QUrl newUrl = getUrl(newName); KIO::Job *job = KIO::moveAs(oldUrl, newUrl, KIO::HideProgressInfo); connectJobToDestination(job, currentDirectory()); KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job); } QUrl DefaultFileSystem::getUrl(const QString& name) const { // NOTE: on non-local fs file URL does not have to be path + name! FileItem *fileItem = getFileItem(name); if (fileItem) return fileItem->getUrl(); QUrl absoluteUrl(_currentDirectory); if (name.startsWith('/')) { absoluteUrl.setPath(name); } else { absoluteUrl.setPath(absoluteUrl.path() + '/' + name); } return absoluteUrl; } void DefaultFileSystem::updateFilesystemInfo() { if (!KConfigGroup(krConfig, "Look&Feel").readEntry("ShowSpaceInformation", true)) { _mountPoint = ""; emit fileSystemInfoChanged(i18n("Space information disabled"), "", 0, 0); return; } // TODO get space info for trash:/ with KIO spaceInfo job if (!_currentDirectory.isLocalFile()) { _mountPoint = ""; emit fileSystemInfoChanged(i18n("No space information on non-local filesystems"), "", 0, 0); return; } const QString path = _currentDirectory.path(); const KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(path); if (!info.isValid()) { _mountPoint = ""; emit fileSystemInfoChanged(i18n("Space information unavailable"), "", 0, 0); return; } _mountPoint = info.mountPoint(); const KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByPath(path); const QString fsType = mountPoint ? mountPoint->mountType() : ""; emit fileSystemInfoChanged("", fsType, info.size(), info.available()); } // ==== protected ==== bool DefaultFileSystem::refreshInternal(const QUrl &directory, bool onlyScan) { qDebug() << "refresh internal to URL=" << directory.toDisplayString(); if (!KProtocolManager::supportsListing(directory)) { emit error(i18n("Protocol not supported by Krusader:\n%1", directory.url())); return false; } delete _watcher; // stop watching the old dir if (directory.isLocalFile()) { qDebug() << "start local refresh to URL=" << directory.toDisplayString(); // we could read local directories with KIO but using Qt is a lot faster! return refreshLocal(directory, onlyScan); } _currentDirectory = cleanUrl(directory); // start the listing job KIO::ListJob *job = KIO::listDir(_currentDirectory, KIO::HideProgressInfo, showHiddenFiles()); connect(job, &KIO::ListJob::entries, this, &DefaultFileSystem::slotAddFiles); connect(job, &KIO::ListJob::redirection, this, &DefaultFileSystem::slotRedirection); connect(job, &KIO::ListJob::permanentRedirection, this, &DefaultFileSystem::slotRedirection); connect(job, &KIO::Job::result, this, &DefaultFileSystem::slotListResult); // ensure connection credentials are asked only once if(!parentWindow.isNull()) { KIO::JobUiDelegate *ui = static_cast(job->uiDelegate()); ui->setWindow(parentWindow); } emit refreshJobStarted(job); _listError = false; // ugly: we have to wait here until the list job is finished QEventLoop eventLoop; connect(job, &KJob::finished, &eventLoop, &QEventLoop::quit); eventLoop.exec(); // blocking until quit() return !_listError; } // ==== protected slots ==== void DefaultFileSystem::slotListResult(KJob *job) { qDebug() << "got list result"; if (job && job->error()) { // we failed to refresh _listError = true; qDebug() << "error=" << job->errorString() << "; text=" << job->errorText(); emit error(job->errorString()); // display error message (in panel) } } void DefaultFileSystem::slotAddFiles(KIO::Job *, const KIO::UDSEntryList& entries) { for (const KIO::UDSEntry entry : entries) { FileItem *fileItem = FileSystem::createFileItemFromKIO(entry, _currentDirectory); if (fileItem) { addFileItem(fileItem); } } } void DefaultFileSystem::slotRedirection(KIO::Job *job, const QUrl &url) { qDebug() << "redirection to URL=" << url.toDisplayString(); // some protocols (zip, tar) send redirect to local URL without scheme const QUrl newUrl = preferLocalUrl(url); if (newUrl.scheme() != _currentDirectory.scheme()) { // abort and start over again, // some protocols (iso, zip, tar) do this on transition to local fs job->kill(); _isRefreshing = false; refresh(newUrl); return; } _currentDirectory = cleanUrl(newUrl); } void DefaultFileSystem::slotWatcherCreated(const QString& path) { qDebug() << "path created (doing nothing): " << path; } void DefaultFileSystem::slotWatcherDirty(const QString& path) { qDebug() << "path dirty: " << path; if (path == realPath()) { // this happens // 1. if a directory was created/deleted/renamed inside this directory. // 2. during and after a file operation (create/delete/rename/touch) inside this directory // KDirWatcher doesn't reveal the name of changed directories and we have to refresh. // (QFileSystemWatcher in Qt5.7 can't help here either) refresh(); return; } const QString name = QUrl::fromLocalFile(path).fileName(); FileItem *fileItem = getFileItem(name); if (!fileItem) { qWarning() << "file not found (unexpected), path=" << path; // this happens at least for cifs mounted filesystems: when a new file is created, a dirty // signal with its file path but no other signals are sent (buggy behaviour of KDirWatch) refresh(); return; } // we have an updated file.. FileItem *newFileItem = createLocalFileItem(name); addFileItem(newFileItem); emit updatedFileItem(newFileItem); delete fileItem; } void DefaultFileSystem::slotWatcherDeleted(const QString& path) { qDebug() << "path deleted: " << path; if (path != _currentDirectory.toLocalFile()) { // ignore deletion of files here, a 'dirty' signal will be send anyway return; } // the current directory was deleted. Try a refresh, which will fail. An error message will // be emitted and the empty (non-existing) directory remains. refresh(); } bool DefaultFileSystem::refreshLocal(const QUrl &directory, bool onlyScan) { const QString path = KrServices::urlToLocalPath(directory); #ifdef Q_WS_WIN if (!path.contains("/")) { // change C: to C:/ path = path + QString("/"); } #endif // check if the new directory exists if (!QDir(path).exists()) { emit error(i18n("The folder %1 does not exist.", path)); return false; } // mount if needed emit aboutToOpenDir(path); // set the current directory... _currentDirectory = directory; _currentDirectory.setPath(QDir::cleanPath(_currentDirectory.path())); // Note: we are using low-level Qt functions here. // It's around twice as fast as using the QDir class. QT_DIR* dir = QT_OPENDIR(path.toLocal8Bit()); if (!dir) { emit error(i18n("Cannot open the folder %1.", path)); return false; } // change directory to the new directory const QString savedDir = QDir::currentPath(); if (!QDir::setCurrent(path)) { emit error(i18nc("%1=folder path", "Access to %1 denied", path)); QT_CLOSEDIR(dir); return false; } QT_DIRENT* dirEnt; QString name; const bool showHidden = showHiddenFiles(); while ((dirEnt = QT_READDIR(dir)) != NULL) { name = QString::fromLocal8Bit(dirEnt->d_name); // show hidden files? if (!showHidden && name.left(1) == ".") continue; // we don't need the "." and ".." entries if (name == "." || name == "..") continue; FileItem* temp = createLocalFileItem(name); addFileItem(temp); } // clean up QT_CLOSEDIR(dir); QDir::setCurrent(savedDir); if (!onlyScan) { // start watching the new dir for file changes _watcher = new KDirWatch(this); // if the current dir is a link path the watcher needs to watch the real path - and signal // parameters will be the real path _watcher->addDir(realPath(), KDirWatch::WatchFiles); connect(_watcher.data(), &KDirWatch::dirty, this, &DefaultFileSystem::slotWatcherDirty); // NOTE: not connecting 'created' signal. A 'dirty' is send after that anyway //connect(_watcher, SIGNAL(created(QString)), this, SLOT(slotWatcherCreated(QString))); connect(_watcher.data(), &KDirWatch::deleted, this, &DefaultFileSystem::slotWatcherDeleted); _watcher->startScan(false); } return true; } FileItem *DefaultFileSystem::createLocalFileItem(const QString &name) { return FileSystem::createLocalFileItem(name, _currentDirectory.path()); } QString DefaultFileSystem::DefaultFileSystem::realPath() { // NOTE: current dir must exist return QDir(_currentDirectory.toLocalFile()).canonicalPath(); } QUrl DefaultFileSystem::resolveRelativePath(const QUrl &url) { // if e.g. "/tmp/bin" is a link to "/bin", // resolve "/tmp/bin/.." to "/tmp" and not "/" return url.adjusted(QUrl::NormalizePathSegments); } diff --git a/krusader/FileSystem/defaultfilesystem.h b/krusader/FileSystem/defaultfilesystem.h index b071612f..24c93150 100644 --- a/krusader/FileSystem/defaultfilesystem.h +++ b/krusader/FileSystem/defaultfilesystem.h @@ -1,105 +1,96 @@ -/*************************************************************************** - defaultfilesystem.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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; 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; /// 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(); } QString mountPoint() const { return _mountPoint; } bool hasAutoUpdate() const Q_DECL_OVERRIDE { return !_watcher.isNull(); } void updateFilesystemInfo() Q_DECL_OVERRIDE; protected: bool refreshInternal(const QUrl &origin, bool onlyScan) Q_DECL_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/fileitem.cpp b/krusader/FileSystem/fileitem.cpp index c0e6483c..6f0dd3cf 100644 --- a/krusader/FileSystem/fileitem.cpp +++ b/krusader/FileSystem/fileitem.cpp @@ -1,240 +1,230 @@ -/*************************************************************************** - fileitem.cpp - ------------------- - copyright : (C) 2000 by Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "fileitem.h" // QtCore #include #include #include #include #include #include "krpermhandler.h" #include "filesystemprovider.h" bool FileItem::userDefinedFolderIcons = true; // wrapper class; QCache needs objects class FileSize { public: const KIO::filesize_t m_size; FileSize(KIO::filesize_t size) : m_size(size) {} }; // cache for calculated directory sizes; static QCache s_fileSizeCache(1000); FileItem::FileItem(const QString &name, const QUrl &url, bool isDir, KIO::filesize_t size, mode_t mode, time_t mtime, time_t ctime, time_t atime, uid_t uid, gid_t gid, const QString &owner, const QString &group, bool isLink, const QString &linkDest, bool isBrokenLink, const QString &acl, const QString &defaultAcl) : m_name(name), m_url(url), m_isDir(isDir), m_size(size), m_mode(mode), m_mtime(mtime), m_ctime(ctime), m_atime(atime), m_uid(uid), m_gid(gid), m_owner(owner), m_group(group), m_isLink(isLink), m_linkDest(linkDest), m_isBrokenLink(isBrokenLink), m_acl(acl), m_defaulfAcl(defaultAcl), m_AclLoaded(false), m_mimeType(), m_icon() { m_permissions = KRpermHandler::mode2QString(mode); if (m_owner.isEmpty()) m_owner = KRpermHandler::uid2user(m_uid); if (m_group.isEmpty()) m_group = KRpermHandler::gid2group(m_gid); if (m_isDir && !m_isLink) { m_size = s_fileSizeCache.contains(m_url) ? s_fileSizeCache[m_url]->m_size : -1; } } FileItem *FileItem::createDummy() { FileItem *file = new FileItem("..", QUrl(), true, 0, 0, 0, 0, 0); file->setIcon("go-up"); return file; } FileItem *FileItem::createBroken(const QString &name, const QUrl &url) { FileItem *file = new FileItem(name, url, false, 0, 0, 0, 0, 0); file->setIcon("file-broken"); return file; } FileItem *FileItem::createVirtualDir(const QString &name, const QUrl &url) { return new FileItem(name, url, true, 0, 0700, time(0), time(0), time(0), getuid(), getgid()); } FileItem *FileItem::createCopy(const FileItem &file, const QString &newName) { return new FileItem(newName, file.getUrl(), file.isDir(), file.getSize(), file.getMode(), file.getTime_t(), file.getChangedTime(), file.getAccessTime(), file.m_uid, file.m_gid, file.getOwner(), file.getGroup(), file.isSymLink(), file.getSymDest(), file.isBrokenLink()); } char FileItem::isReadable() const { if (m_uid != (uid_t)-1 && m_gid != (gid_t)-1) return KRpermHandler::readable(m_permissions, m_gid, m_uid); else return KRpermHandler::ftpReadable(m_owner, m_url.userName(), m_permissions); } char FileItem::isWriteable() const { if (m_uid != (uid_t)-1 && m_gid != (gid_t)-1) return KRpermHandler::writeable(m_permissions, m_gid, m_uid); else return KRpermHandler::ftpWriteable(m_owner, m_url.userName(), m_permissions); } char FileItem::isExecutable() const { if (m_uid != (uid_t)-1 && m_gid != (gid_t)-1) return KRpermHandler::executable(m_permissions, m_gid, m_uid); else return KRpermHandler::ftpExecutable(m_owner, m_url.userName(), m_permissions); } void FileItem::setSize(KIO::filesize_t size) { m_size = size; s_fileSizeCache.insert(m_url, new FileSize(size)); } const QString &FileItem::getMime() { if (m_mimeType.isEmpty()) { if (m_isDir) { m_mimeType = "inode/directory"; m_icon = "inode-directory"; } else if (isBrokenLink()) { m_mimeType = "unknown"; m_icon = "file-broken"; } else { const QMimeDatabase db; const QMimeType mt = db.mimeTypeForUrl(getUrl()); m_mimeType = mt.isValid() ? mt.name() : "unknown"; m_icon = mt.isValid() ? mt.iconName() : "file-broken"; if (m_mimeType == "inode/directory") { // TODO view update needed? and does this ever happen? m_isDir = true; } } if (m_isDir && userDefinedFolderIcons) { const QUrl url = getUrl(); if (url.isLocalFile()) { const QString file = url.toLocalFile() + "/.directory"; const KDesktopFile cfg(file); const QString icon = cfg.readIcon(); if (!icon.isEmpty()) m_icon = icon.startsWith(QLatin1String("./")) ? // relative path url.toLocalFile() + '/' + icon : icon; } } } return m_mimeType; } const QString &FileItem::getIcon() { if (m_icon.isEmpty()) { getMime(); // sets the icon } return m_icon; } const QString &FileItem::getACL() { if (!m_AclLoaded) loadACL(); return m_acl; } void FileItem::loadACL() { if (m_url.isLocalFile()) { FileSystemProvider::getACL(this, m_acl, m_defaulfAcl); } m_AclLoaded = true; } const KIO::UDSEntry FileItem::getEntry() { KIO::UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_NAME, getName()); entry.insert(KIO::UDSEntry::UDS_SIZE, getSize()); entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, getTime_t()); entry.insert(KIO::UDSEntry::UDS_CREATION_TIME, getChangedTime()); entry.insert(KIO::UDSEntry::UDS_ACCESS_TIME, getAccessTime()); entry.insert(KIO::UDSEntry::UDS_USER, getOwner()); entry.insert(KIO::UDSEntry::UDS_GROUP, getGroup()); entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, getMime()); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, getMode() & S_IFMT); entry.insert(KIO::UDSEntry::UDS_ACCESS, getMode() & 07777); if (isSymLink()) entry.insert(KIO::UDSEntry::UDS_LINK_DEST, getSymDest()); if (!m_AclLoaded) loadACL(); if (!m_acl.isNull() || !m_defaulfAcl.isNull()) { entry.insert(KIO::UDSEntry::UDS_EXTENDED_ACL, 1); if (!m_acl.isNull()) entry.insert(KIO::UDSEntry::UDS_ACL_STRING, m_acl); if (!m_defaulfAcl.isNull()) entry.insert(KIO::UDSEntry::UDS_DEFAULT_ACL_STRING, m_defaulfAcl); } return entry; } diff --git a/krusader/FileSystem/fileitem.h b/krusader/FileSystem/fileitem.h index 8fabfbdb..fb1f6b96 100644 --- a/krusader/FileSystem/fileitem.h +++ b/krusader/FileSystem/fileitem.h @@ -1,171 +1,163 @@ -/*************************************************************************** - fileitem.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef FILEITEM_H #define FILEITEM_H #include // QtCore #include #include #include #include /** * A file item gives access all meta information of a (virtual, dummy or real) file or directory in * the filesystem. * * NOTE: The name of a file item is supposed to be unique within a directory. */ class FileItem { public: /** * Create a new file item. * * Don't use this constructor outside of FileSystem! If you really need to, create a new static * factory method below. * * NOTE: According to Unix standard uid and gid CAN have signed or unsigned type. We use (e.g.) * "(uid_t) -1" as a special invalid user ID for non-local files. * NOTE: ACLs are currently only used by Synchronizer. * * @param name the display name of this file. Don't have to be the real filename. * @param url (real) absolute URL of this file * @param isDir true if this file is a directory. Else false. * @param size size of file * @param mode mode of file (file type and permissions) * @param mtime file modification time * @param ctime file changed time * @param atime file access time * @param uid Unix user id of file owner. Use -1 here and provide an owner name for non-local files. * @param gid Unix group id of file group. Use -1 here and provide a group name for non-local files. * @param owner user name of file owner. Can be empty for local files * @param group group name of file group. Can be empty for local files. * @param isLink true if file is a symbolic link. Else false. * @param linkDest link destination path if file is a link. Relative or absolute. Empty by default. * @param isBrokenLink true if file is a symbolic link and destination file does not exists. Else false. * @param acl ACL string of file. Can be empty and is loaded on demand. * @param defaultAcl default ACL string of file (only for directories). Can be empty and is loaded on demand. */ FileItem(const QString &name, const QUrl &url, bool isDir, KIO::filesize_t size, mode_t mode, time_t mtime, time_t ctime, time_t atime, uid_t uid = -1, gid_t gid = -1, const QString &owner = QString(), const QString &group = QString(), bool isLink = false, const QString &linkDest = QString(), bool isBrokenLink = false, const QString &acl = QString(), const QString &defaultAcl = QString()); /** Create a new ".." dummy file item. */ static FileItem *createDummy(); /** Create a file item for a broken file which metadata could not be read. */ static FileItem *createBroken(const QString &name, const QUrl &url); /** Create a new virtual directory. */ static FileItem *createVirtualDir(const QString &name, const QUrl &url); /** Create a new file item copy with a different name. */ static FileItem *createCopy(const FileItem &file, const QString &newName); // following functions give-out file details inline const QString &getName() const { return m_name; } /** Return the file size. Returns 0 for directories with unknown size. */ inline KIO::filesize_t getSize() const { return m_size == (KIO::filesize_t)-1 ? 0 : m_size; } /** Return the file size. Returns (KIO::filesize_t)-1 for directories with unknown size. */ inline KIO::filesize_t getUISize() const { return m_size; } inline const QString &getPerm() const { return m_permissions; } inline bool isDir() const { return m_isDir; } inline bool isSymLink() const { return m_isLink; } inline bool isBrokenLink() const { return m_isBrokenLink; } inline const QString &getSymDest() const { return m_linkDest; } inline mode_t getMode() const { return m_mode; } inline time_t getTime_t() const { return m_mtime; } inline time_t getChangedTime() const { return m_ctime; } inline time_t getAccessTime() const { return m_atime; } inline const QUrl &getUrl() const { return m_url; } inline const QString &getOwner() const { return m_owner; } inline const QString &getGroup() const { return m_group; } const QString &getMime(); const QString &getIcon(); const QString &getACL(); const QString &getDefaultACL(); const KIO::UDSEntry getEntry(); //< return the UDSEntry from the file item char isReadable() const; char isWriteable() const; char isExecutable() const; /** * Set the file size. * used ONLY when calculating a directory's space, needs to change the * displayed size of the viewitem and thus the file item. For INTERNAL USE ! */ void setSize(KIO::filesize_t size); inline static void loadUserDefinedFolderIcons(bool load) { userDefinedFolderIcons = load; } private: void setIcon(const QString &icon) { m_icon = icon; m_mimeType = "?"; } void loadACL(); QString m_name; //< file name QUrl m_url; //< file URL bool m_isDir; //< flag, true if it's a directory KIO::filesize_t m_size; //< file size mode_t m_mode; //< file mode (file type and permissions) time_t m_mtime; //< file modification time time_t m_ctime; //< file changed time time_t m_atime; //< file access time uid_t m_uid; //< file owner id gid_t m_gid; //< file group id QString m_owner; //< file owner name QString m_group; //< file group name bool m_isLink; //< true if the file is a symlink QString m_linkDest; //< if it's a sym link - its detination bool m_isBrokenLink; //< true if the link destianation does not exist QString m_permissions; //< file permissions string QString m_acl; //< ACL permission string, may lazy initialized QString m_defaulfAcl; //< ACL default string, may lazy initialized bool m_AclLoaded; //< flag, indicates that ACL permissions already loaded QString m_mimeType; //< file mimetype, lazy initialized QString m_icon; //< the name of the icon file, lazy initialized static bool userDefinedFolderIcons; }; #endif diff --git a/krusader/FileSystem/filesystem.cpp b/krusader/FileSystem/filesystem.cpp index 837d519f..2c8e27e0 100644 --- a/krusader/FileSystem/filesystem.cpp +++ b/krusader/FileSystem/filesystem.cpp @@ -1,352 +1,340 @@ -/*************************************************************************** - filesystem.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - ------------------------------------------------------------------------ - the filesystem class is an extendable class which by itself does (almost) - nothing. other filesystems like the normal_filesystem inherits from this class and - make it possible to use a consistent API for all types of filesystems. - - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include #include "filesystem.h" // QtCore #include #include #include // QtWidgets #include #include #include #include #include "fileitem.h" #include "krpermhandler.h" #include "../defaults.h" #include "../krglobal.h" #include "../JobMan/jobman.h" #include "../JobMan/krjob.h" FileSystem::FileSystem() : DirListerInterface(0), _isRefreshing(false) {} FileSystem::~FileSystem() { clear(_fileItems); // please don't remove this line. This informs the view about deleting the file items. emit cleared(); } QList FileSystem::getUrls(const QStringList &names) const { QList urls; for (const QString name : names) { urls.append(getUrl(name)); } return urls; } FileItem *FileSystem::getFileItem(const QString &name) const { return _fileItems.contains(name) ? _fileItems.value(name) : 0; } KIO::filesize_t FileSystem::totalSize() const { KIO::filesize_t temp = 0; for (FileItem *item : _fileItems.values()) { if (!item->isDir() && item->getName() != "." && item->getName() != "..") { temp += item->getSize(); } } return temp; } QUrl FileSystem::ensureTrailingSlash(const QUrl &url) { if (url.path().endsWith('/')) { return url; } QUrl adjustedUrl(url); adjustedUrl.setPath(adjustedUrl.path() + '/'); return adjustedUrl; } QUrl FileSystem::preferLocalUrl(const QUrl &url){ if (url.isEmpty() || !url.scheme().isEmpty()) return url; QUrl adjustedUrl = url; adjustedUrl.setScheme("file"); return adjustedUrl; } bool FileSystem::scanOrRefresh(const QUrl &directory, bool onlyScan) { qDebug() << "from current dir=" << _currentDirectory.toDisplayString() << "; to=" << directory.toDisplayString(); if (_isRefreshing) { // NOTE: this does not happen (unless async)"; return false; } // workaround for krarc: find out if transition to local fs is wanted and adjust URL manually QUrl url = directory; if (_currentDirectory.scheme() == "krarc" && url.scheme() == "krarc" && QDir(url.path()).exists()) { url.setScheme("file"); } const bool dirChange = !url.isEmpty() && cleanUrl(url) != _currentDirectory; const QUrl toRefresh = dirChange ? url.adjusted(QUrl::NormalizePathSegments) : _currentDirectory; if (!toRefresh.isValid()) { emit error(i18n("Malformed URL:\n%1", toRefresh.toDisplayString())); return false; } _isRefreshing = true; FileItemDict tempFileItems(_fileItems); // old file items are still used during refresh _fileItems.clear(); if (dirChange) // show an empty directory while loading the new one and clear selection emit cleared(); const bool refreshed = refreshInternal(toRefresh, onlyScan); _isRefreshing = false; if (!refreshed) { // cleanup and abort if (!dirChange) emit cleared(); clear(tempFileItems); return false; } emit scanDone(dirChange); clear(tempFileItems); updateFilesystemInfo(); return true; } void FileSystem::deleteFiles(const QStringList &fileNames, bool moveToTrash) { // get absolute URLs for file names deleteAnyFiles(getUrls(fileNames), moveToTrash); } void FileSystem::deleteAnyFiles(const QList &urls, bool moveToTrash) { KrJob *krJob = KrJob::createDeleteJob(urls, moveToTrash); connect(krJob, &KrJob::started, this, [=](KIO::Job *job) { connectJobToSources(job, urls); }); if (moveToTrash) { // update destination: the trash bin (in case a panel/tab is showing it) connect(krJob, &KrJob::started, this, [=](KIO::Job *job) { // Note: the "trash" protocal should always have only one "/" after the "scheme:" part connect(job, &KIO::Job::result, this, [=]() { emit fileSystemChanged(QUrl("trash:/"), false); }); }); } krJobMan->manageJob(krJob); } void FileSystem::connectJobToSources(KJob *job, const QList urls) { if (!urls.isEmpty()) { // TODO we assume that all files were in the same directory and only emit one signal for // the directory of the first file URL (all subdirectories of parent are notified) const QUrl url = urls.first().adjusted(QUrl::RemoveFilename); connect(job, &KIO::Job::result, this, [=]() { emit fileSystemChanged(url, true); }); } } void FileSystem::connectJobToDestination(KJob *job, const QUrl &destination) { connect(job, &KIO::Job::result, this, [=]() { emit fileSystemChanged(destination, false); }); // (additional) direct refresh if on local fs because watcher is too slow const bool refresh = cleanUrl(destination) == _currentDirectory && isLocal(); connect(job, &KIO::Job::result, this, [=](KJob* job) { slotJobResult(job, refresh); }); } bool FileSystem::showHiddenFiles() { const KConfigGroup gl(krConfig, "Look&Feel"); return gl.readEntry("Show Hidden", _ShowHidden); } void FileSystem::addFileItem(FileItem *item) { _fileItems.insert(item->getName(), item); } FileItem *FileSystem::createLocalFileItem(const QString &name, const QString &directory, bool virt) { const QDir dir = QDir(directory); const QString path = dir.filePath(name); const QByteArray pathByteArray = path.toLocal8Bit(); const QString fileItemName = virt ? path : name; const QUrl fileItemUrl = QUrl::fromLocalFile(path); // read file status; in case of error create a "broken" file item QT_STATBUF stat_p; memset(&stat_p, 0, sizeof(stat_p)); if (QT_LSTAT(pathByteArray.data(), &stat_p) < 0) return FileItem::createBroken(fileItemName, fileItemUrl); const KIO::filesize_t size = stat_p.st_size; bool isDir = S_ISDIR(stat_p.st_mode); const bool isLink = S_ISLNK(stat_p.st_mode); // for links, read link destination and determine whether it's broken or not QString linkDestination; bool brokenLink = false; if (isLink) { linkDestination = readLinkSafely(pathByteArray.data()); if (linkDestination.isNull()) { brokenLink = true; } else { const QFileInfo linkFile(dir, linkDestination); if (!linkFile.exists()) brokenLink = true; else if (linkFile.isDir()) isDir = true; } } // create normal file item return new FileItem(fileItemName, fileItemUrl, isDir, size, stat_p.st_mode, stat_p.st_mtime, stat_p.st_ctime, stat_p.st_atime, stat_p.st_uid, stat_p.st_gid, QString(), QString(), isLink, linkDestination, brokenLink); } QString FileSystem::readLinkSafely(const char *path) { // inspired by the areadlink_with_size function from gnulib, which is used for coreutils // idea: start with a small buffer and gradually increase it as we discover it wasn't enough QT_OFF_T bufferSize = 1024; // start with 1 KiB QT_OFF_T maxBufferSize = std::numeric_limits::max(); while (true) { // try to read the link std::unique_ptr buffer(new char[bufferSize]); auto nBytesRead = readlink(path, buffer.get(), bufferSize); // should never happen, asserted by the readlink if (nBytesRead > bufferSize) { return QString(); } // read failure if (nBytesRead < 0) { qDebug() << "Failed to read the link " << path; return QString(); } // read success if (nBytesRead < bufferSize || nBytesRead == maxBufferSize) { return QString::fromLocal8Bit(buffer.get(), nBytesRead); } // increase the buffer and retry again // bufferSize < maxBufferSize is implied from previous checks if (bufferSize <= maxBufferSize / 2) { bufferSize *= 2; } else { bufferSize = maxBufferSize; } } } FileItem *FileSystem::createFileItemFromKIO(const KIO::UDSEntry &entry, const QUrl &directory, bool virt) { const KFileItem kfi(entry, directory, true, true); const QString name = kfi.text(); // ignore un-needed entries if (name.isEmpty() || name == "." || name == "..") { return 0; } const QString localPath = kfi.localPath(); const QUrl url = !localPath.isEmpty() ? QUrl::fromLocalFile(localPath) : kfi.url(); const QString fname = virt ? url.toDisplayString() : name; // get file statistics... const time_t mtime = kfi.time(KFileItem::ModificationTime).toTime_t(); const time_t ctime = kfi.time(KFileItem::CreationTime).toTime_t(); // "Creation"? its "Changed" const time_t atime = kfi.time(KFileItem::AccessTime).toTime_t(); const mode_t mode = kfi.mode() | kfi.permissions(); // NOTE: we could get the mimetype (and file icon) from the kfileitem here but this is very // slow. Instead, the file item class has it's own (faster) way to determine the file type. // NOTE: "broken link" flag is always false, checking link destination existence is // considered to be too expensive return new FileItem(fname, url, kfi.isDir(), kfi.size(), mode, mtime, ctime, atime, (uid_t) -1, (gid_t) -1, kfi.user(), kfi.group(), kfi.isLink(), kfi.linkDest(), false, kfi.ACL().asString(), kfi.defaultACL().asString()); } void FileSystem::slotJobResult(KJob *job, bool refresh) { if (job->error() && job->uiDelegate()) { // show errors for modifying operations as popup (works always) job->uiDelegate()->showErrorMessage(); } if (refresh) { FileSystem::refresh(); } } void FileSystem::clear(FileItemDict &fileItems) { QHashIterator lit(fileItems); while (lit.hasNext()) { delete lit.next().value(); } fileItems.clear(); } diff --git a/krusader/FileSystem/filesystem.h b/krusader/FileSystem/filesystem.h index 601e51fe..3e42aea9 100644 --- a/krusader/FileSystem/filesystem.h +++ b/krusader/FileSystem/filesystem.h @@ -1,231 +1,223 @@ -/*************************************************************************** - filesystem.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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(); virtual ~FileSystem(); // DirListerInterface implementation inline QList fileItems() const { return _fileItems.values(); } inline unsigned long numFileItems() const { return _fileItems.count(); } inline bool isRoot() const { 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 files in the current directory. Implemented async. void deleteFiles(const QStringList &fileNames, bool moveToTrash = true); /// Delete or trash arbitrary files. Implemented async. Universal refresh not fully implemented. void deleteAnyFiles(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/krpermhandler.cpp b/krusader/FileSystem/krpermhandler.cpp index 25ed69f2..644b3bb5 100644 --- a/krusader/FileSystem/krpermhandler.cpp +++ b/krusader/FileSystem/krpermhandler.cpp @@ -1,188 +1,179 @@ -/*************************************************************************** - krpermhandler.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krpermhandler.h" // QtCore #include #include #include #include QSet KRpermHandler::currentGroups; QHash KRpermHandler::uidCache; QHash KRpermHandler::gidCache; QString KRpermHandler::mode2QString(mode_t m) { char perm[ 11 ]; for (int i = 0; i != 10; i++) perm[ i ] = '-'; perm[ 10 ] = 0; if (S_ISLNK(m)) perm[ 0 ] = 'l'; // check for symLink if (S_ISDIR(m)) perm[ 0 ] = 'd'; // check for directory //ReadUser = 0400, WriteUser = 0200, ExeUser = 0100, Suid = 04000 if (m & 0400) perm[ 1 ] = 'r'; if (m & 0200) perm[ 2 ] = 'w'; if (m & 0100) perm[ 3 ] = 'x'; if (m & 04000) perm[ 3 ] = 's'; //ReadGroup = 0040, WriteGroup = 0020, ExeGroup = 0010, Gid = 02000 if (m & 0040) perm[ 4 ] = 'r'; if (m & 0020) perm[ 5 ] = 'w'; if (m & 0010) perm[ 6 ] = 'x'; if (m & 02000) perm[ 6 ] = 's'; //ReadOther = 0004, WriteOther = 0002, ExeOther = 0001, Sticky = 01000 if (m & 0004) perm[ 7 ] = 'r'; if (m & 0002) perm[ 8 ] = 'w'; if (m & 0001) perm[ 9 ] = 'x'; if (m & 01000) perm[ 9 ] = 't'; return QString(perm); } void KRpermHandler::init() { // set the umask to 022 //umask( 022 ); // 200 groups should be enough gid_t groupList[200]; int groupNo = getgroups(200, groupList); // In kdewin32 implementation as of 4.1.2, getpwent always returns the same struct #ifndef Q_WS_WIN // fill the UID cache struct passwd *pass; while ((pass = getpwent()) != 0L) { uidCache.insert(pass->pw_uid, pass->pw_name); } delete pass; endpwent(); // fill the GID cache struct group *gr; while ((gr = getgrent()) != 0L) { gidCache.insert(gr->gr_gid, QString(gr->gr_name)); } delete gr; endgrent(); #endif // fill the groups for the current user for (int i = 0; i < groupNo; ++i) { currentGroups.insert(groupList[i]); } // just to be sure add the effective gid... currentGroups.insert(getegid()); } char KRpermHandler::readable(const QString &perm, gid_t gid, uid_t uid) { return getLocalPermission(perm, gid, uid, 0); } char KRpermHandler::writeable(const QString &perm, gid_t gid, uid_t uid) { return getLocalPermission(perm, gid, uid, 1); } char KRpermHandler::executable(const QString &perm, gid_t gid, uid_t uid) { return getLocalPermission(perm, gid, uid, 2, true); } char KRpermHandler::getLocalPermission(const QString &perm, gid_t gid, uid_t uid, int permOffset, bool ignoreRoot) { // root override if (!ignoreRoot && getuid() == 0) return ALLOWED_PERM; // first check other permissions. if (perm[7 + permOffset] != '-') return ALLOWED_PERM; // now check group permission if ((perm[4 + permOffset] != '-') && currentGroups.contains(gid)) return ALLOWED_PERM; // the last chance - user permissions if ((perm[1 + permOffset] != '-') && (uid == getuid())) return ALLOWED_PERM; // sorry ! return NO_PERM; } char KRpermHandler::ftpReadable(const QString &fileOwner, const QString &userName, const QString &perm) { return getFtpPermission(fileOwner, userName, perm, 0); } char KRpermHandler::ftpWriteable(const QString &fileOwner, const QString &userName, const QString &perm) { return getFtpPermission(fileOwner, userName, perm, 1); } char KRpermHandler::ftpExecutable(const QString &fileOwner, const QString &userName, const QString &perm) { return getFtpPermission(fileOwner, userName, perm, 2); } char KRpermHandler::getFtpPermission(const QString &fileOwner, const QString &userName, const QString &perm, int permOffset) { // first check other permissions. if (perm[7 + permOffset] != '-') return ALLOWED_PERM; // can't check group permission ! // so check the user permissions if ((perm[1 + permOffset] != '-') && (fileOwner == userName)) return ALLOWED_PERM; if ((perm[1 + permOffset] != '-') && (userName.isEmpty())) return UNKNOWN_PERM; if (perm[4 + permOffset] != '-') return UNKNOWN_PERM; return NO_PERM; } QString KRpermHandler::parseSize(KIO::filesize_t val) { return QLocale().toString(val); } QString KRpermHandler::gid2group(gid_t groupId) { return gidCache.value(groupId, QStringLiteral("???")); } QString KRpermHandler::uid2user(uid_t userId) { return uidCache.value(userId, QStringLiteral("???")); } diff --git a/krusader/FileSystem/krpermhandler.h b/krusader/FileSystem/krpermhandler.h index ea8984d0..62f774cb 100644 --- a/krusader/FileSystem/krpermhandler.h +++ b/krusader/FileSystem/krpermhandler.h @@ -1,81 +1,72 @@ -/*************************************************************************** - krpermhandler.h - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRPERMHANDLER_H #define KRPERMHANDLER_H // QtCore #include #include #include #include #include #include #include #define NO_PERM 0 #define UNKNOWN_PERM 1 #define ALLOWED_PERM 2 class KRpermHandler { public: static void init(); static QString gid2group(gid_t groupId); static QString uid2user(uid_t userId); static char writeable(const QString &perm, gid_t gid, uid_t uid); static char readable(const QString &perm, gid_t gid, uid_t uid); static char executable(const QString &perm, gid_t gid, uid_t uid); static char ftpWriteable(const QString &fileOwner, const QString & userName, const QString &perm); static char ftpReadable(const QString &fileOwner, const QString &userName, const QString &perm); static char ftpExecutable(const QString &fileOwner, const QString &userName, const QString &perm); static QString mode2QString(mode_t m); static QString parseSize(KIO::filesize_t val); private: KRpermHandler() {} static char getLocalPermission(const QString &perm, gid_t gid, uid_t uid, int permOffset, bool ignoreRoot = false); static char getFtpPermission(const QString &fileOwner, const QString &userName, const QString &perm, int permOffset); static QSet currentGroups; static QHash uidCache; static QHash gidCache; }; #endif diff --git a/krusader/FileSystem/krquery.cpp b/krusader/FileSystem/krquery.cpp index fbedf07d..2a6ceb53 100644 --- a/krusader/FileSystem/krquery.cpp +++ b/krusader/FileSystem/krquery.cpp @@ -1,786 +1,777 @@ -/*************************************************************************** - krquery.cpp - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krquery.h" // QtCore #include #include #include #include #include #include #include #include #include "../Archive/krarchandler.h" #include "fileitem.h" #include "filesystem.h" #include "krpermhandler.h" #define STATUS_SEND_DELAY 250 #define MAX_LINE_LEN 1000 // set the defaults KRQuery::KRQuery() : QObject(), matchesCaseSensitive(true), bNull(true), contain(QString()), containCaseSensetive(true), containWholeWord(false), containRegExp(false), minSize(0), maxSize(0), newerThen(0), olderThen(0), owner(QString()), group(QString()), perm(QString()), type(QString()), inArchive(false), recurse(true), followLinksP(true), receivedBuffer(0), receivedBufferLen(0), processEventsConnected(0), codec(QTextCodec::codecForLocale()) { QChar ch = '\n'; QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); encodedEnterArray = codec->fromUnicode(&ch, 1, &state); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); } // set the defaults KRQuery::KRQuery(const QString &name, bool matchCase) : QObject(), bNull(true), contain(QString()), containCaseSensetive(true), containWholeWord(false), containRegExp(false), minSize(0), maxSize(0), newerThen(0), olderThen(0), owner(QString()), group(QString()), perm(QString()), type(QString()), inArchive(false), recurse(true), followLinksP(true), receivedBuffer(0), receivedBufferLen(0), processEventsConnected(0), codec(QTextCodec::codecForLocale()) { QChar ch = '\n'; QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); encodedEnterArray = codec->fromUnicode(&ch, 1, &state); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); setNameFilter(name, matchCase); } KRQuery::KRQuery(const KRQuery &that) : QObject(), receivedBuffer(0), receivedBufferLen(0), processEventsConnected(0) { *this = that; } KRQuery::~KRQuery() { if (receivedBuffer) delete[] receivedBuffer; receivedBuffer = 0; } KRQuery &KRQuery::operator=(const KRQuery &old) { matches = old.matches; excludes = old.excludes; includedDirs = old.includedDirs; excludedDirs = old.excludedDirs; matchesCaseSensitive = old.matchesCaseSensitive; bNull = old.bNull; contain = old.contain; containCaseSensetive = old.containCaseSensetive; containWholeWord = old.containWholeWord; containRegExp = old.containRegExp; minSize = old.minSize; maxSize = old.maxSize; newerThen = old.newerThen; olderThen = old.olderThen; owner = old.owner; group = old.group; perm = old.perm; type = old.type; customType = old.customType; inArchive = old.inArchive; recurse = old.recurse; followLinksP = old.followLinksP; whereToSearch = old.whereToSearch; excludedFolderNames = old.excludedFolderNames; whereNotToSearch = old.whereNotToSearch; origFilter = old.origFilter; codec = old.codec; encodedEnterArray = old.encodedEnterArray; encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); return *this; } void KRQuery::load(KConfigGroup cfg) { *this = KRQuery(); // reset parameters first if (cfg.readEntry("IsNull", true)) return; #define LOAD(key, var) (var = cfg.readEntry(key, var)) LOAD("Matches", matches); LOAD("Excludes", excludes); LOAD("IncludedDirs", includedDirs); LOAD("ExcludedDirs", excludedDirs); LOAD("MatchesCaseSensitive", matchesCaseSensitive); LOAD("Contain", contain); LOAD("ContainCaseSensetive", containCaseSensetive); LOAD("ContainWholeWord", containWholeWord); LOAD("ContainRegExp", containRegExp); LOAD("MinSize", minSize); LOAD("MaxSize", maxSize); newerThen = QDateTime::fromString( cfg.readEntry("NewerThan", QDateTime::fromTime_t(newerThen).toString())) .toTime_t(); olderThen = QDateTime::fromString( cfg.readEntry("OlderThan", QDateTime::fromTime_t(olderThen).toString())) .toTime_t(); LOAD("Owner", owner); LOAD("Group", group); LOAD("Perm", perm); LOAD("Type", type); LOAD("CustomType", customType); LOAD("InArchive", inArchive); LOAD("Recurse", recurse); LOAD("FollowLinks", followLinksP); // KF5 TODO? // LOAD("WhereToSearch", whereToSearch); // LOAD("WhereNotToSearch", whereNotToSearch); LOAD("OrigFilter", origFilter); codec = QTextCodec::codecForName(cfg.readEntry("Codec", codec->name())); if (!codec) codec = QTextCodec::codecForLocale(); LOAD("EncodedEnterArray", encodedEnterArray); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); #undef LOAD bNull = false; } void KRQuery::save(KConfigGroup cfg) { cfg.writeEntry("IsNull", bNull); if (bNull) return; cfg.writeEntry("Matches", matches); cfg.writeEntry("Excludes", excludes); cfg.writeEntry("IncludedDirs", includedDirs); cfg.writeEntry("ExcludedDirs", excludedDirs); cfg.writeEntry("MatchesCaseSensitive", matchesCaseSensitive); cfg.writeEntry("Contain", contain); cfg.writeEntry("ContainCaseSensetive", containCaseSensetive); cfg.writeEntry("ContainWholeWord", containWholeWord); cfg.writeEntry("ContainRegExp", containRegExp); cfg.writeEntry("MinSize", minSize); cfg.writeEntry("MaxSize", maxSize); cfg.writeEntry("NewerThan", QDateTime::fromTime_t(newerThen).toString()); cfg.writeEntry("OlderThan", QDateTime::fromTime_t(olderThen).toString()); cfg.writeEntry("Owner", owner); cfg.writeEntry("Group", group); cfg.writeEntry("Perm", perm); cfg.writeEntry("Type", type); cfg.writeEntry("CustomType", customType); cfg.writeEntry("InArchive", inArchive); cfg.writeEntry("Recurse", recurse); cfg.writeEntry("FollowLinks", followLinksP); // KF5 TODO? // cfg.writeEntry("WhereToSearch", whereToSearch); // cfg.writeEntry("WhereNotToSearch", whereNotToSearch); cfg.writeEntry("OrigFilter", origFilter); cfg.writeEntry("Codec", codec->name()); cfg.writeEntry("EncodedEnterArray", encodedEnterArray); cfg.writeEntry("EncodedEnter", encodedEnter); cfg.writeEntry("EncodedEnterLen", encodedEnterLen); } void KRQuery::connectNotify(const QMetaMethod &signal) { if (signal == QMetaMethod::fromSignal(&KRQuery::processEvents)) processEventsConnected++; } void KRQuery::disconnectNotify(const QMetaMethod &signal) { if (signal == QMetaMethod::fromSignal(&KRQuery::processEvents)) processEventsConnected--; } bool KRQuery::checkPerm(QString filePerm) const { for (int i = 0; i < 9; ++i) if (perm[i] != '?' && perm[i] != filePerm[i + 1]) return false; return true; } bool KRQuery::checkType(QString mime) const { if (type == mime) return true; if (type == i18n("Archives")) return KRarcHandler::arcSupported(mime); if (type == i18n("Folders")) return mime.contains("directory"); if (type == i18n("Image Files")) return mime.contains("image/"); if (type == i18n("Text Files")) return mime.contains("text/"); if (type == i18n("Video Files")) return mime.contains("video/"); if (type == i18n("Audio Files")) return mime.contains("audio/"); if (type == i18n("Custom")) return customType.contains(mime); return false; } bool KRQuery::match(const QString &name) const { return matchCommon(name, matches, excludes); } bool KRQuery::matchDirName(const QString &name) const { return matchCommon(name, includedDirs, excludedDirs); } bool KRQuery::matchCommon(const QString &nameIn, const QStringList &matchList, const QStringList &excludeList) const { if (excludeList.count() == 0 && matchList.count() == 0) /* true if there's no match condition */ return true; QString name(nameIn); int ndx = nameIn.lastIndexOf('/'); // virtual filenames may contain '/' if (ndx != -1) // but the end of the filename is OK name = nameIn.mid(ndx + 1); for (int i = 0; i < excludeList.count(); ++i) { if (QRegExp(excludeList[i], matchesCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard) .exactMatch(name)) return false; } if (matchList.count() == 0) return true; for (int i = 0; i < matchList.count(); ++i) { if (QRegExp(matchList[i], matchesCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard) .exactMatch(name)) return true; } return false; } bool KRQuery::match(FileItem *item) const { if (item->isDir() && !matchDirName(item->getName())) return false; // see if the name matches if (!match(item->getName())) return false; // checking the mime if (!type.isEmpty() && !checkType(item->getMime())) return false; // check that the size fit KIO::filesize_t size = item->getSize(); if (minSize && size < minSize) return false; if (maxSize && size > maxSize) return false; // check the time frame time_t mtime = item->getTime_t(); if (olderThen && mtime > olderThen) return false; if (newerThen && mtime < newerThen) return false; // check owner name if (!owner.isEmpty() && item->getOwner() != owner) return false; // check group name if (!group.isEmpty() && item->getGroup() != group) return false; // check permission if (!perm.isEmpty() && !checkPerm(item->getPerm())) return false; if (!contain.isEmpty()) { if ((totalBytes = item->getSize()) == 0) totalBytes++; // sanity receivedBytes = 0; if (receivedBuffer) delete receivedBuffer; receivedBuffer = 0; receivedBufferLen = 0; fileName = item->getName(); timer.start(); // search locally if (item->getUrl().isLocalFile()) { return containsContent(item->getUrl().path()); } // search remotely if (processEventsConnected == 0) { return false; } return containsContent(item->getUrl()); } return true; } // takes the string and adds BOLD to it, so that when it is displayed, // the grepped text will be bold void fixFoundTextForDisplay(QString &haystack, int start, int length) { QString before = haystack.left(start); QString text = haystack.mid(start, length); QString after = haystack.mid(start + length); before.replace('&', "&"); before.replace('<', "<"); before.replace('>', ">"); text.replace('&', "&"); text.replace('<', "<"); text.replace('>', ">"); after.replace('&', "&"); after.replace('<', "<"); after.replace('>', ">"); haystack = ("" + before + "" + text + "" + after + ""); } bool KRQuery::checkBuffer(const char *data, int len) const { bool result = false; char *mergedBuffer = new char[len + receivedBufferLen]; if (receivedBufferLen) memcpy(mergedBuffer, receivedBuffer, receivedBufferLen); if (len) memcpy(mergedBuffer + receivedBufferLen, data, len); int maxLen = len + receivedBufferLen; int maxBuffer = maxLen - encodedEnterLen; int lastLinePosition = 0; for (int enterIndex = 0; enterIndex < maxBuffer; enterIndex++) { if (memcmp(mergedBuffer + enterIndex, encodedEnter, encodedEnterLen) == 0) { QString str = codec->toUnicode(mergedBuffer + lastLinePosition, enterIndex + encodedEnterLen - lastLinePosition); if (str.endsWith('\n')) { str.chop(1); result = result || checkLine(str); lastLinePosition = enterIndex + encodedEnterLen; enterIndex = lastLinePosition; continue; } } } if (maxLen - lastLinePosition > MAX_LINE_LEN || len == 0) { QString str = codec->toUnicode(mergedBuffer + lastLinePosition, maxLen - lastLinePosition); result = result || checkLine(str); lastLinePosition = maxLen; } delete[] receivedBuffer; receivedBuffer = 0; receivedBufferLen = maxLen - lastLinePosition; if (receivedBufferLen) { receivedBuffer = new char[receivedBufferLen]; memcpy(receivedBuffer, mergedBuffer + lastLinePosition, receivedBufferLen); } delete[] mergedBuffer; return result; } bool KRQuery::checkLine(const QString &line, bool backwards) const { if (containRegExp) { QRegExp rexp(contain, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::RegExp); int ndx = backwards ? rexp.lastIndexIn(line) : rexp.indexIn(line); bool result = ndx >= 0; if (result) fixFoundTextForDisplay(lastSuccessfulGrep = line, lastSuccessfulGrepMatchIndex = ndx, lastSuccessfulGrepMatchLength = rexp.matchedLength()); return result; } int ndx = backwards ? -1 : 0; if (line.isNull()) return false; if (containWholeWord) { while ((ndx = (backwards) ? line.lastIndexOf(contain, ndx, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive) : line.indexOf(contain, ndx, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive)) != -1) { QChar before = '\n'; QChar after = '\n'; if (ndx > 0) before = line.at(ndx - 1); if (ndx + contain.length() < line.length()) after = line.at(ndx + contain.length()); if (!before.isLetterOrNumber() && !after.isLetterOrNumber() && after != '_' && before != '_') { lastSuccessfulGrep = line; fixFoundTextForDisplay(lastSuccessfulGrep, lastSuccessfulGrepMatchIndex = ndx, lastSuccessfulGrepMatchLength = contain.length()); return true; } if (backwards) ndx -= line.length() + 1; else ndx++; } } else if ((ndx = (backwards) ? line.lastIndexOf(contain, -1, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive) : line.indexOf(contain, 0, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive)) != -1) { lastSuccessfulGrep = line; fixFoundTextForDisplay(lastSuccessfulGrep, lastSuccessfulGrepMatchIndex = ndx, lastSuccessfulGrepMatchLength = contain.length()); return true; } return false; } bool KRQuery::containsContent(QString file) const { QFile qf(file); if (!qf.open(QIODevice::ReadOnly)) return false; char buffer[1440]; // 2k buffer while (!qf.atEnd()) { int bytes = qf.read(buffer, sizeof(buffer)); if (bytes <= 0) break; receivedBytes += bytes; if (checkBuffer(buffer, bytes)) return true; if (checkTimer()) { bool stopped = false; emit((KRQuery *)this)->processEvents(stopped); if (stopped) return false; } } if (checkBuffer(buffer, 0)) return true; lastSuccessfulGrep.clear(); // nothing was found return false; } bool KRQuery::containsContent(QUrl url) const { KIO::TransferJob *contentReader = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); connect(contentReader, &KIO::TransferJob::data, this, &KRQuery::containsContentData); connect(contentReader, &KIO::Job::result, this, &KRQuery::containsContentFinished); busy = true; containsContentResult = false; bool stopped = false; while (busy && !stopped) { checkTimer(); emit((KRQuery *)this)->processEvents(stopped); } if (busy) { contentReader->kill(KJob::EmitResult); busy = false; } return containsContentResult; } void KRQuery::containsContentData(KIO::Job *job, const QByteArray &array) { receivedBytes += array.size(); if (checkBuffer(array.data(), array.size())) { containsContentResult = true; containsContentFinished(job); job->kill(KJob::EmitResult); return; } checkTimer(); } void KRQuery::containsContentFinished(KJob *) { busy = false; } bool KRQuery::checkTimer() const { if (timer.elapsed() >= STATUS_SEND_DELAY) { int pcnt = (int)(100. * (double)receivedBytes / (double)totalBytes + .5); QString message = i18nc("%1=filename, %2=percentage", "Searching content of '%1' (%2%)", fileName, pcnt); timer.start(); emit((KRQuery *)this)->status(message); return true; } return false; } QStringList KRQuery::split(QString str) { QStringList list; int splitNdx = 0; int startNdx = 0; bool quotation = false; while (splitNdx < str.length()) { if (str[splitNdx] == '"') quotation = !quotation; if (!quotation && str[splitNdx] == ' ') { QString section = str.mid(startNdx, splitNdx - startNdx); startNdx = splitNdx + 1; if (section.startsWith('\"') && section.endsWith('\"') && section.length() >= 2) section = section.mid(1, section.length() - 2); if (!section.isEmpty()) list.append(section); } splitNdx++; } if (startNdx < splitNdx) { QString section = str.mid(startNdx, splitNdx - startNdx); if (section.startsWith('\"') && section.endsWith('\"') && section.length() >= 2) section = section.mid(1, section.length() - 2); if (!section.isEmpty()) list.append(section); } return list; } void KRQuery::setNameFilter(const QString &text, bool cs) { bNull = false; matchesCaseSensitive = cs; origFilter = text; QString matchText = text; QString excludeText; int excludeNdx = 0; bool quotationMark = 0; while (excludeNdx < matchText.length()) { if (matchText[excludeNdx] == '"') quotationMark = !quotationMark; if (!quotationMark) { if (matchText[excludeNdx] == '|') break; } excludeNdx++; } if (excludeNdx < matchText.length()) { excludeText = matchText.mid(excludeNdx + 1).trimmed(); matchText.truncate(excludeNdx); matchText = matchText.trimmed(); if (matchText.isEmpty()) matchText = '*'; } int i; matches = split(matchText); includedDirs.clear(); for (i = 0; i < matches.count();) { if (matches[i].endsWith('/')) { includedDirs.push_back(matches[i].left(matches[i].length() - 1)); matches.removeAll(matches.at(i)); continue; } if (!matches[i].contains("*") && !matches[i].contains("?")) matches[i] = '*' + matches[i] + '*'; i++; } excludes = split(excludeText); excludedDirs.clear(); for (i = 0; i < excludes.count();) { if (excludes[i].endsWith('/')) { excludedDirs.push_back(excludes[i].left(excludes[i].length() - 1)); excludes.removeAll(excludes.at(i)); continue; } if (!excludes[i].contains("*") && !excludes[i].contains("?")) excludes[i] = '*' + excludes[i] + '*'; i++; } } void KRQuery::setContent(const QString &content, bool cs, bool wholeWord, QString encoding, bool regExp) { bNull = false; contain = content; containCaseSensetive = cs; containWholeWord = wholeWord; containRegExp = regExp; if (encoding.isEmpty()) codec = QTextCodec::codecForLocale(); else { codec = QTextCodec::codecForName(encoding.toLatin1()); if (codec == 0) codec = QTextCodec::codecForLocale(); } QChar ch = '\n'; QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); encodedEnterArray = codec->fromUnicode(&ch, 1, &state); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); } void KRQuery::setMinimumFileSize(KIO::filesize_t minimumSize) { bNull = false; minSize = minimumSize; } void KRQuery::setMaximumFileSize(KIO::filesize_t maximumSize) { bNull = false; maxSize = maximumSize; } void KRQuery::setNewerThan(time_t time) { bNull = false; newerThen = time; } void KRQuery::setOlderThan(time_t time) { bNull = false; olderThen = time; } void KRQuery::setOwner(const QString &ownerIn) { bNull = false; owner = ownerIn; } void KRQuery::setGroup(const QString &groupIn) { bNull = false; group = groupIn; } void KRQuery::setPermissions(const QString &permIn) { bNull = false; perm = permIn; } void KRQuery::setMimeType(const QString &typeIn, QStringList customList) { bNull = false; type = typeIn; customType = customList; } bool KRQuery::isExcluded(const QUrl &url) { for (QUrl &item : whereNotToSearch) if (item.isParentOf(url) || url.matches(item, QUrl::StripTrailingSlash)) return true; // Exclude folder names that are configured in settings QString filename = url.fileName(); for (QString &item : excludedFolderNames) if (filename == item) return true; if (!matchDirName(filename)) return true; return false; } void KRQuery::setSearchInDirs(const QList &urls) { whereToSearch.clear(); for (int i = 0; i < urls.count(); ++i) { QString url = urls[i].url(); QUrl completed = QUrl::fromUserInput(KUrlCompletion::replacedPath(url, true, true), QString(), QUrl::AssumeLocalFile); whereToSearch.append(completed); } } void KRQuery::setDontSearchInDirs(const QList &urls) { whereNotToSearch.clear(); for (int i = 0; i < urls.count(); ++i) { QString url = urls[i].url(); QUrl completed = QUrl::fromUserInput(KUrlCompletion::replacedPath(url, true, true), QString(), QUrl::AssumeLocalFile); whereNotToSearch.append(completed); } } void KRQuery::setExcludeFolderNames(const QStringList &paths) { excludedFolderNames.clear(); excludedFolderNames.append(paths); } diff --git a/krusader/FileSystem/krquery.h b/krusader/FileSystem/krquery.h index eee78b4c..8bf93b70 100644 --- a/krusader/FileSystem/krquery.h +++ b/krusader/FileSystem/krquery.h @@ -1,237 +1,228 @@ -/*************************************************************************** - krquery.h - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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 virtual ~KRQuery(); // load parameters from config void load(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, 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 virtual void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; // important to know whether the event processor is connected virtual void disconnectNotify(const QMetaMethod &signal) Q_DECL_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(QString mime) const; bool containsContent(QString file) const; bool containsContent(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/krtrashhandler.cpp b/krusader/FileSystem/krtrashhandler.cpp index 8125c72e..46e9b8b3 100644 --- a/krusader/FileSystem/krtrashhandler.cpp +++ b/krusader/FileSystem/krtrashhandler.cpp @@ -1,126 +1,116 @@ -/*************************************************************************** - krtrashhandler.cpp - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krtrashhandler.h" // QtCore #include #include #include #include #include #include #include #include #include #include "filesystemprovider.h" #include "../kractions.h" #include "../krglobal.h" KrTrashWatcher * KrTrashHandler::_trashWatcher = 0; bool KrTrashHandler::isTrashEmpty() { KConfig trashConfig("trashrc"); KConfigGroup cfg(&trashConfig, "Status"); return cfg.readEntry("Empty", false); } QString KrTrashHandler::trashIcon() { return isTrashEmpty() ? "user-trash" : "user-trash-full"; } void KrTrashHandler::emptyTrash() { KIO::JobUiDelegate uiDelegate; uiDelegate.setWindow(krMainWindow); if (!uiDelegate.askDeleteConfirmation(QList(), KIO::JobUiDelegate::EmptyTrash, KIO::JobUiDelegate::DefaultConfirmation)) return; KIO::Job *job = KIO::emptyTrash(); KJobWidgets::setWindow(job, krMainWindow); job->uiDelegate()->setAutoErrorHandlingEnabled(true); const QUrl url = QUrl("trash:/"); QObject::connect(job, &KIO::Job::result, [=]() { FileSystemProvider::instance().refreshFilesystems(url, false); }); } void KrTrashHandler::restoreTrashedFiles(const QList &urls) { if (urls.isEmpty()) return; KIO::RestoreJob *job = KIO::restoreFromTrash(urls); KJobWidgets::setWindow(job, krMainWindow); job->uiDelegate()->setAutoErrorHandlingEnabled(true); const QUrl url = urls.first().adjusted(QUrl::RemoveFilename); QObject::connect(job, &KIO::Job::result, [=]() { FileSystemProvider::instance().refreshFilesystems(url, false); }); } void KrTrashHandler::startWatcher() { if (!_trashWatcher) _trashWatcher = new KrTrashWatcher(); } void KrTrashHandler::stopWatcher() { delete _trashWatcher; _trashWatcher = 0; } KrTrashWatcher::KrTrashWatcher() { _watcher = new KDirWatch(); connect(_watcher, &KDirWatch::created, this, &KrTrashWatcher::slotTrashChanged); connect(_watcher, &KDirWatch::dirty, this, &KrTrashWatcher::slotTrashChanged); const QString trashrcFile = QDir(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)).filePath("trashrc"); _watcher->addFile(trashrcFile); _watcher->startScan(true); } KrTrashWatcher::~KrTrashWatcher() { delete _watcher; _watcher = 0; } void KrTrashWatcher::slotTrashChanged() { KrActions::actTrashBin->setIcon(QIcon::fromTheme(KrTrashHandler::trashIcon())); } diff --git a/krusader/FileSystem/krtrashhandler.h b/krusader/FileSystem/krtrashhandler.h index 63528d9a..85c26a8e 100644 --- a/krusader/FileSystem/krtrashhandler.h +++ b/krusader/FileSystem/krtrashhandler.h @@ -1,73 +1,63 @@ -/*************************************************************************** - krtrashhandler.h - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRTRASHHANDLER_H #define KRTRASHHANDLER_H // QtCore #include #include #include class KrTrashWatcher; class KrTrashHandler { public: static bool isTrashEmpty(); static QString trashIcon(); static void emptyTrash(); static void restoreTrashedFiles(const QList &url); static void startWatcher(); static void stopWatcher(); private: static KrTrashWatcher * _trashWatcher; }; /** Watches the trashrc config file for changes and updates the trash icon. */ class KrTrashWatcher : public QObject { Q_OBJECT public: KrTrashWatcher(); virtual ~KrTrashWatcher(); public slots: void slotTrashChanged(); private: KDirWatch * _watcher; }; #endif /* __KR_TRASH_HANDLER__ */ diff --git a/krusader/Filter/advancedfilter.cpp b/krusader/Filter/advancedfilter.cpp index 539b1426..1949fc91 100644 --- a/krusader/Filter/advancedfilter.cpp +++ b/krusader/Filter/advancedfilter.cpp @@ -1,620 +1,612 @@ -/*************************************************************************** - advancedfilter.cpp - description - ------------------- - copyright : (C) 2003 + by Shie Erlich & Rafi Yanai & Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "advancedfilter.h" // QtCore #include #include #include // QtGui #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include "../krglobal.h" #include "../Dialogs/krdialogs.h" #define USERSFILE QString("/etc/passwd") #define GROUPSFILE QString("/etc/group") AdvancedFilter::AdvancedFilter(FilterTabs *tabs, QWidget *parent) : QWidget(parent), fltTabs(tabs) { QGridLayout *filterLayout = new QGridLayout(this); filterLayout->setSpacing(6); filterLayout->setContentsMargins(11, 11, 11, 11); // Options for size QGroupBox *sizeGroup = new QGroupBox(this); QSizePolicy sizeGroupPolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); sizeGroupPolicy.setHeightForWidth(sizeGroup->sizePolicy().hasHeightForWidth()); sizeGroup->setSizePolicy(sizeGroupPolicy); sizeGroup->setTitle(i18n("Size")); QGridLayout *sizeLayout = new QGridLayout(sizeGroup); sizeLayout->setAlignment(Qt::AlignTop); sizeLayout->setSpacing(6); sizeLayout->setContentsMargins(11, 11, 11, 11); minSizeEnabled = new QCheckBox(sizeGroup); minSizeEnabled->setText(i18n("At Least")); minSizeEnabled->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); sizeLayout->addWidget(minSizeEnabled, 0, 0); minSizeAmount = new QSpinBox(sizeGroup); minSizeAmount->setRange(0, 999999999); minSizeAmount->setEnabled(false); sizeLayout->addWidget(minSizeAmount, 0, 1); minSizeType = new KComboBox(false, sizeGroup); // i18n: @item:inlistbox next to a text field containing the amount minSizeType->addItem(i18n("Byte")); // i18n: @item:inlistbox next to a text field containing the amount minSizeType->addItem(i18n("KiB")); // i18n: @item:inlistbox next to a text field containing the amount minSizeType->addItem(i18n("MiB")); // i18n: @item:inlistbox next to a text field containing the amount minSizeType->addItem(i18n("GiB")); minSizeType->setEnabled(false); sizeLayout->addWidget(minSizeType, 0, 2); maxSizeEnabled = new QCheckBox(sizeGroup); maxSizeEnabled->setText(i18n("At Most")); maxSizeEnabled->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); sizeLayout->addWidget(maxSizeEnabled, 0, 3); maxSizeAmount = new QSpinBox(sizeGroup); maxSizeAmount->setRange(0, 999999999); maxSizeAmount->setEnabled(false); sizeLayout->addWidget(maxSizeAmount, 0, 4); maxSizeType = new KComboBox(false, sizeGroup); // i18n: @item:inlistbox next to a text field containing the amount maxSizeType->addItem(i18n("Byte")); // i18n: @item:inlistbox next to a text field containing the amount maxSizeType->addItem(i18n("KiB")); // i18n: @item:inlistbox next to a text field containing the amount maxSizeType->addItem(i18n("MiB")); // i18n: @item:inlistbox next to a text field containing the amount maxSizeType->addItem(i18n("GiB")); maxSizeType->setEnabled(false); sizeLayout->addWidget(maxSizeType, 0, 5); filterLayout->addWidget(sizeGroup, 0, 0); // Options for date QPixmap iconDate = krLoader->loadIcon("view-calendar", KIconLoader::Toolbar, 16); QGroupBox *dateGroup = new QGroupBox(this); QButtonGroup *btnGroup = new QButtonGroup(dateGroup); dateGroup->setTitle(i18n("Date")); btnGroup->setExclusive(true); QGridLayout *dateLayout = new QGridLayout(dateGroup); dateLayout->setAlignment(Qt::AlignTop); dateLayout->setSpacing(6); dateLayout->setContentsMargins(11, 11, 11, 11); anyDateEnabled = new QRadioButton(dateGroup); anyDateEnabled->setText(i18n("Any date")); btnGroup->addButton(anyDateEnabled); anyDateEnabled->setChecked(true); modifiedBetweenEnabled = new QRadioButton(dateGroup); modifiedBetweenEnabled->setText(i18n("&Modified between")); btnGroup->addButton(modifiedBetweenEnabled); modifiedBetweenData1 = new KLineEdit(dateGroup); modifiedBetweenData1->setEnabled(false); modifiedBetweenData1->setText(""); modifiedBetweenBtn1 = new QToolButton(dateGroup); modifiedBetweenBtn1->setEnabled(false); modifiedBetweenBtn1->setText(""); modifiedBetweenBtn1->setIcon(QIcon(iconDate)); QLabel *andLabel = new QLabel(dateGroup); andLabel->setText(i18n("an&d")); modifiedBetweenData2 = new KLineEdit(dateGroup); modifiedBetweenData2->setEnabled(false); modifiedBetweenData2->setText(""); andLabel->setBuddy(modifiedBetweenData2); modifiedBetweenBtn2 = new QToolButton(dateGroup); modifiedBetweenBtn2->setEnabled(false); modifiedBetweenBtn2->setText(""); modifiedBetweenBtn2->setIcon(QIcon(iconDate)); notModifiedAfterEnabled = new QRadioButton(dateGroup); notModifiedAfterEnabled->setText(i18n("&Not modified after")); btnGroup->addButton(notModifiedAfterEnabled); notModifiedAfterData = new KLineEdit(dateGroup); notModifiedAfterData->setEnabled(false); notModifiedAfterData->setText(""); notModifiedAfterBtn = new QToolButton(dateGroup); notModifiedAfterBtn->setEnabled(false); notModifiedAfterBtn->setText(""); notModifiedAfterBtn->setIcon(QIcon(iconDate)); modifiedInTheLastEnabled = new QRadioButton(dateGroup); modifiedInTheLastEnabled->setText(i18n("Mod&ified in the last")); btnGroup->addButton(modifiedInTheLastEnabled); modifiedInTheLastData = new QSpinBox(dateGroup); modifiedInTheLastData->setRange(0, 99999); modifiedInTheLastData->setEnabled(false); modifiedInTheLastType = new KComboBox(dateGroup); modifiedInTheLastType->addItem(i18n("days")); modifiedInTheLastType->addItem(i18n("weeks")); modifiedInTheLastType->addItem(i18n("months")); modifiedInTheLastType->addItem(i18n("years")); modifiedInTheLastType->setEnabled(false); notModifiedInTheLastData = new QSpinBox(dateGroup); notModifiedInTheLastData->setRange(0, 99999); notModifiedInTheLastData->setEnabled(false); QLabel *notModifiedInTheLastLbl = new QLabel(dateGroup); notModifiedInTheLastLbl->setText(i18n("No&t modified in the last")); notModifiedInTheLastLbl->setBuddy(notModifiedInTheLastData); notModifiedInTheLastType = new KComboBox(dateGroup); notModifiedInTheLastType->addItem(i18n("days")); notModifiedInTheLastType->addItem(i18n("weeks")); notModifiedInTheLastType->addItem(i18n("months")); notModifiedInTheLastType->addItem(i18n("years")); notModifiedInTheLastType->setEnabled(false); // Date options layout dateLayout->addWidget(anyDateEnabled, 0, 0); dateLayout->addWidget(modifiedBetweenEnabled, 1, 0); dateLayout->addWidget(modifiedBetweenData1, 1, 1); dateLayout->addWidget(modifiedBetweenBtn1, 1, 2); dateLayout->addWidget(andLabel, 1, 3); dateLayout->addWidget(modifiedBetweenData2, 1, 4); dateLayout->addWidget(modifiedBetweenBtn2, 1, 5); dateLayout->addWidget(notModifiedAfterEnabled, 2, 0); dateLayout->addWidget(notModifiedAfterData, 2, 1); dateLayout->addWidget(notModifiedAfterBtn, 2, 2); dateLayout->addWidget(modifiedInTheLastEnabled, 3, 0); QHBoxLayout *modifiedInTheLastLayout = new QHBoxLayout(); modifiedInTheLastLayout->addWidget(modifiedInTheLastData); modifiedInTheLastLayout->addWidget(modifiedInTheLastType); dateLayout->addLayout(modifiedInTheLastLayout, 3, 1); dateLayout->addWidget(notModifiedInTheLastLbl, 4, 0); modifiedInTheLastLayout = new QHBoxLayout(); modifiedInTheLastLayout->addWidget(notModifiedInTheLastData); modifiedInTheLastLayout->addWidget(notModifiedInTheLastType); dateLayout->addLayout(modifiedInTheLastLayout, 4, 1); filterLayout->addWidget(dateGroup, 1, 0); // Options for ownership QGroupBox *ownershipGroup = new QGroupBox(this); ownershipGroup->setTitle(i18n("Ownership")); QGridLayout *ownershipLayout = new QGridLayout(ownershipGroup); ownershipLayout->setAlignment(Qt::AlignTop); ownershipLayout->setSpacing(6); ownershipLayout->setContentsMargins(11, 11, 11, 11); QHBoxLayout *hboxLayout = new QHBoxLayout(); hboxLayout->setSpacing(6); hboxLayout->setContentsMargins(0, 0, 0, 0); belongsToUserEnabled = new QCheckBox(ownershipGroup); belongsToUserEnabled->setText(i18n("Belongs to &user")); hboxLayout->addWidget(belongsToUserEnabled); belongsToUserData = new KComboBox(ownershipGroup); belongsToUserData->setEnabled(false); belongsToUserData->setEditable(false); hboxLayout->addWidget(belongsToUserData); belongsToGroupEnabled = new QCheckBox(ownershipGroup); belongsToGroupEnabled->setText(i18n("Belongs to gr&oup")); hboxLayout->addWidget(belongsToGroupEnabled); belongsToGroupData = new KComboBox(ownershipGroup); belongsToGroupData->setEnabled(false); belongsToGroupData->setEditable(false); hboxLayout->addWidget(belongsToGroupData); ownershipLayout->addLayout(hboxLayout, 0, 0, 1, 4); permissionsEnabled = new QCheckBox(ownershipGroup); permissionsEnabled->setText(i18n("P&ermissions")); ownershipLayout->addWidget(permissionsEnabled, 1, 0); QGroupBox *ownerGroup = new QGroupBox(ownershipGroup); QHBoxLayout *ownerHBox = new QHBoxLayout(ownerGroup); ownerGroup->setTitle(i18n("O&wner")); ownerR = new KComboBox(ownerGroup); ownerR->addItem(i18n("?")); ownerR->addItem(i18n("r")); ownerR->addItem(i18n("-")); ownerR->setEnabled(false); ownerHBox->addWidget(ownerR); ownerW = new KComboBox(ownerGroup); ownerW->addItem(i18n("?")); ownerW->addItem(i18n("w")); ownerW->addItem(i18n("-")); ownerW->setEnabled(false); ownerHBox->addWidget(ownerW); ownerX = new KComboBox(ownerGroup); ownerX->addItem(i18n("?")); ownerX->addItem(i18n("x")); ownerX->addItem(i18n("-")); ownerX->setEnabled(false); ownerHBox->addWidget(ownerX); ownershipLayout->addWidget(ownerGroup, 1, 1); QGroupBox *groupGroup = new QGroupBox(ownershipGroup); QHBoxLayout *groupHBox = new QHBoxLayout(groupGroup); groupGroup->setTitle(i18n("Grou&p")); groupR = new KComboBox(groupGroup); groupR->addItem(i18n("?")); groupR->addItem(i18n("r")); groupR->addItem(i18n("-")); groupR->setEnabled(false); groupHBox->addWidget(groupR); groupW = new KComboBox(groupGroup); groupW->addItem(i18n("?")); groupW->addItem(i18n("w")); groupW->addItem(i18n("-")); groupW->setEnabled(false); groupHBox->addWidget(groupW); groupX = new KComboBox(groupGroup); groupX->addItem(i18n("?")); groupX->addItem(i18n("x")); groupX->addItem(i18n("-")); groupX->setEnabled(false); groupHBox->addWidget(groupX); ownershipLayout->addWidget(groupGroup, 1, 2); QGroupBox *allGroup = new QGroupBox(ownershipGroup); QHBoxLayout *allHBox = new QHBoxLayout(allGroup); allGroup->setTitle(i18n("A&ll")); allR = new KComboBox(allGroup); allR->addItem(i18n("?")); allR->addItem(i18n("r")); allR->addItem(i18n("-")); allR->setEnabled(false); allHBox->addWidget(allR); allW = new KComboBox(allGroup); allW->addItem(i18n("?")); allW->addItem(i18n("w")); allW->addItem(i18n("-")); allW->setEnabled(false); allHBox->addWidget(allW); allX = new KComboBox(allGroup); allX->addItem(i18n("?")); allX->addItem(i18n("x")); allX->addItem(i18n("-")); allX->setEnabled(false); allHBox->addWidget(allX); ownershipLayout->addWidget(allGroup, 1, 3); QLabel *infoLabel = new QLabel(ownershipGroup); QFont infoLabel_font(infoLabel->font()); infoLabel_font.setFamily("adobe-helvetica"); infoLabel_font.setItalic(true); infoLabel->setFont(infoLabel_font); infoLabel->setText(i18n("Note: a '?' is a wildcard")); ownershipLayout->addWidget(infoLabel, 2, 0, 1, 4, Qt::AlignRight); filterLayout->addWidget(ownershipGroup, 2, 0); // Connection table connect(minSizeEnabled, SIGNAL(toggled(bool)), minSizeAmount, SLOT(setEnabled(bool))); connect(minSizeEnabled, SIGNAL(toggled(bool)), minSizeType, SLOT(setEnabled(bool))); connect(maxSizeEnabled, SIGNAL(toggled(bool)), maxSizeAmount, SLOT(setEnabled(bool))); connect(maxSizeEnabled, SIGNAL(toggled(bool)), maxSizeType, SLOT(setEnabled(bool))); connect(modifiedBetweenEnabled, SIGNAL(toggled(bool)), modifiedBetweenData1, SLOT(setEnabled(bool))); connect(modifiedBetweenEnabled, SIGNAL(toggled(bool)), modifiedBetweenBtn1, SLOT(setEnabled(bool))); connect(modifiedBetweenEnabled, SIGNAL(toggled(bool)), modifiedBetweenData2, SLOT(setEnabled(bool))); connect(modifiedBetweenEnabled, SIGNAL(toggled(bool)), modifiedBetweenBtn2, SLOT(setEnabled(bool))); connect(notModifiedAfterEnabled, SIGNAL(toggled(bool)), notModifiedAfterData, SLOT(setEnabled(bool))); connect(notModifiedAfterEnabled, SIGNAL(toggled(bool)), notModifiedAfterBtn, SLOT(setEnabled(bool))); connect(modifiedInTheLastEnabled, SIGNAL(toggled(bool)), modifiedInTheLastData, SLOT(setEnabled(bool))); connect(modifiedInTheLastEnabled, SIGNAL(toggled(bool)), modifiedInTheLastType, SLOT(setEnabled(bool))); connect(modifiedInTheLastEnabled, SIGNAL(toggled(bool)), notModifiedInTheLastData, SLOT(setEnabled(bool))); connect(modifiedInTheLastEnabled, SIGNAL(toggled(bool)), notModifiedInTheLastType, SLOT(setEnabled(bool))); connect(belongsToUserEnabled, SIGNAL(toggled(bool)), belongsToUserData, SLOT(setEnabled(bool))); connect(belongsToGroupEnabled, SIGNAL(toggled(bool)), belongsToGroupData, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), ownerR, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), ownerW, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), ownerX, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), groupR, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), groupW, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), groupX, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), allR, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), allW, SLOT(setEnabled(bool))); connect(permissionsEnabled, SIGNAL(toggled(bool)), allX, SLOT(setEnabled(bool))); connect(modifiedBetweenBtn1, SIGNAL(clicked()), this, SLOT(modifiedBetweenSetDate1())); connect(modifiedBetweenBtn2, SIGNAL(clicked()), this, SLOT(modifiedBetweenSetDate2())); connect(notModifiedAfterBtn, SIGNAL(clicked()), this, SLOT(notModifiedAfterSetDate())); // fill the users and groups list fillList(belongsToUserData, USERSFILE); fillList(belongsToGroupData, GROUPSFILE); // tab order setTabOrder(minSizeEnabled, minSizeAmount); setTabOrder(minSizeAmount, maxSizeEnabled); setTabOrder(maxSizeEnabled, maxSizeAmount); setTabOrder(maxSizeAmount, modifiedBetweenEnabled); setTabOrder(modifiedBetweenEnabled, modifiedBetweenData1); setTabOrder(modifiedBetweenData1, modifiedBetweenData2); setTabOrder(modifiedBetweenData2, notModifiedAfterEnabled); setTabOrder(notModifiedAfterEnabled, notModifiedAfterData); setTabOrder(notModifiedAfterData, modifiedInTheLastEnabled); setTabOrder(modifiedInTheLastEnabled, modifiedInTheLastData); setTabOrder(modifiedInTheLastData, notModifiedInTheLastData); setTabOrder(notModifiedInTheLastData, belongsToUserEnabled); setTabOrder(belongsToUserEnabled, belongsToUserData); setTabOrder(belongsToUserData, belongsToGroupEnabled); setTabOrder(belongsToGroupEnabled, belongsToGroupData); setTabOrder(belongsToGroupData, permissionsEnabled); setTabOrder(permissionsEnabled, ownerR); setTabOrder(ownerR, ownerW); setTabOrder(ownerW, ownerX); setTabOrder(ownerX, groupR); setTabOrder(groupR, groupW); setTabOrder(groupW, groupX); setTabOrder(groupX, allR); setTabOrder(allR, allW); setTabOrder(allW, allX); setTabOrder(allX, minSizeType); setTabOrder(minSizeType, maxSizeType); setTabOrder(maxSizeType, modifiedInTheLastType); setTabOrder(modifiedInTheLastType, notModifiedInTheLastType); } void AdvancedFilter::modifiedBetweenSetDate1() { changeDate(modifiedBetweenData1); } void AdvancedFilter::modifiedBetweenSetDate2() { changeDate(modifiedBetweenData2); } void AdvancedFilter::notModifiedAfterSetDate() { changeDate(notModifiedAfterData); } void AdvancedFilter::changeDate(KLineEdit *p) { // check if the current date is valid QDate d = stringToDate(p->text()); if (!d.isValid()) d = QDate::currentDate(); KRGetDate *gd = new KRGetDate(d, this); d = gd->getDate(); // if a user pressed ESC or closed the dialog, we'll return an invalid date if (d.isValid()) p->setText(dateToString(d)); delete gd; } void AdvancedFilter::fillList(KComboBox *list, QString filename) { QFile data(filename); if (!data.open(QIODevice::ReadOnly)) { qWarning() << "Search: Unable to read " << filename << " !!!"; return; } // and read it into the temporary array QTextStream t(&data); while (!t.atEnd()) { QString s = t.readLine(); QString name = s.left(s.indexOf(':')); if (!name.startsWith('#')) list->addItem(name); } } void AdvancedFilter::invalidDateMessage(KLineEdit *p) { // FIXME p->text() is empty sometimes (to reproduce, set date to "13.09.005") KMessageBox::detailedError(this, i18n("Invalid date entered."), i18n("The date %1 is not valid according to your locale. Please re-enter a valid date (use the date button for easy access).", p->text())); p->setFocus(); } bool AdvancedFilter::getSettings(FilterSettings &s) { s.minSizeEnabled = minSizeEnabled->isChecked(); s.minSize.amount = minSizeAmount->value(); s.minSize.unit = static_cast(minSizeType->currentIndex()); s.maxSizeEnabled = maxSizeEnabled->isChecked(); s.maxSize.amount = maxSizeAmount->value(); s.maxSize.unit = static_cast(maxSizeType->currentIndex()); if (s.minSizeEnabled && s.maxSizeEnabled && (s.maxSize.size() < s.minSize.size())) { KMessageBox::detailedError(this, i18n("Specified sizes are inconsistent."), i18n("Please re-enter the values, so that the left side size " "will be smaller than (or equal to) the right side size.")); minSizeAmount->setFocus(); return false; } s.modifiedBetweenEnabled = modifiedBetweenEnabled->isChecked(); s.modifiedBetween1 = stringToDate(modifiedBetweenData1->text()); s.modifiedBetween2 = stringToDate(modifiedBetweenData2->text()); if (s.modifiedBetweenEnabled) { // check if date is valid if (!s.modifiedBetween1.isValid()) { invalidDateMessage(modifiedBetweenData1); return false; } else if (!s.modifiedBetween2.isValid()) { invalidDateMessage(modifiedBetweenData2); return false; } else if (s.modifiedBetween1 > s.modifiedBetween2) { KMessageBox::detailedError(this, i18n("Dates are inconsistent."), i18n("The date on the left is later than the date on the right. " "Please re-enter the dates, so that the left side date " "will be earlier than the right side date.")); modifiedBetweenData1->setFocus(); return false; } } s.notModifiedAfterEnabled = notModifiedAfterEnabled->isChecked(); s.notModifiedAfter = stringToDate(notModifiedAfterData->text()); if(s.notModifiedAfterEnabled && !s.notModifiedAfter.isValid()) { invalidDateMessage(notModifiedAfterData); return false; } s.modifiedInTheLastEnabled = modifiedInTheLastEnabled->isChecked(); s.modifiedInTheLast.amount = modifiedInTheLastData->value(); s.modifiedInTheLast.unit = static_cast(modifiedInTheLastType->currentIndex()); s.notModifiedInTheLast.amount = notModifiedInTheLastData->value(); s.notModifiedInTheLast.unit = static_cast(notModifiedInTheLastType->currentIndex()); if (s.modifiedInTheLastEnabled && s.modifiedInTheLast.amount && s.notModifiedInTheLast.amount) { if (s.modifiedInTheLast.days() < s.notModifiedInTheLast.days()) { KMessageBox::detailedError(this, i18n("Dates are inconsistent."), i18n("The date on top is later than the date on the bottom. " "Please re-enter the dates, so that the top date " "will be earlier than the bottom date.")); modifiedInTheLastData->setFocus(); return false; } } s.ownerEnabled = belongsToUserEnabled->isChecked(); s.owner = belongsToUserData->currentText(); s.groupEnabled = belongsToGroupEnabled->isChecked(); s.group = belongsToGroupData->currentText(); s.permissionsEnabled = permissionsEnabled->isChecked(); s.permissions = ownerR->currentText() + ownerW->currentText() + ownerX->currentText() + groupR->currentText() + groupW->currentText() + groupX->currentText() + allR->currentText() + allW->currentText() + allX->currentText(); return true; } void AdvancedFilter::applySettings(const FilterSettings &s) { minSizeEnabled->setChecked(s.minSizeEnabled); minSizeAmount->setValue(s.minSize.amount); minSizeType->setCurrentIndex(s.minSize.unit); maxSizeEnabled->setChecked(s.maxSizeEnabled); maxSizeAmount->setValue(s.maxSize.amount); maxSizeType->setCurrentIndex(s.maxSize.unit); if (s.modifiedBetweenEnabled) modifiedBetweenEnabled->setChecked(true); else if (s.notModifiedAfterEnabled) notModifiedAfterEnabled->setChecked(true); else if (s.modifiedInTheLastEnabled) modifiedInTheLastEnabled->setChecked(true); else anyDateEnabled->setChecked(true); modifiedBetweenData1->setText(dateToString(s.modifiedBetween1)); modifiedBetweenData2->setText(dateToString(s.modifiedBetween2)); notModifiedAfterData->setText(dateToString(s.notModifiedAfter)); modifiedInTheLastData->setValue(s.modifiedInTheLast.amount); modifiedInTheLastType->setCurrentIndex(s.modifiedInTheLast.unit); notModifiedInTheLastData->setValue(s.notModifiedInTheLast.amount); notModifiedInTheLastType->setCurrentIndex(s.notModifiedInTheLast.unit); belongsToUserEnabled->setChecked(s.ownerEnabled); setComboBoxValue(belongsToUserData, s.owner); belongsToGroupEnabled->setChecked(s.groupEnabled); setComboBoxValue(belongsToGroupData, s.group); permissionsEnabled->setChecked(s.permissionsEnabled); QString perm = s.permissions; if (perm.length() != 9) perm = "?????????"; setComboBoxValue(ownerR, QString(perm[0])); setComboBoxValue(ownerW, QString(perm[1])); setComboBoxValue(ownerX, QString(perm[2])); setComboBoxValue(groupR, QString(perm[3])); setComboBoxValue(groupW, QString(perm[4])); setComboBoxValue(groupX, QString(perm[5])); setComboBoxValue(allR, QString(perm[6])); setComboBoxValue(allW, QString(perm[7])); setComboBoxValue(allX, QString(perm[8])); } diff --git a/krusader/Filter/advancedfilter.h b/krusader/Filter/advancedfilter.h index bdc53303..5b8a0171 100644 --- a/krusader/Filter/advancedfilter.h +++ b/krusader/Filter/advancedfilter.h @@ -1,128 +1,120 @@ -/*************************************************************************** - advancedfilter.h - description - ------------------- - copyright : (C) 2003 + by Shie Erlich & Rafi Yanai & Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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 = 0); virtual void queryAccepted() Q_DECL_OVERRIDE {} virtual QString name() Q_DECL_OVERRIDE { return "AdvancedFilter"; } virtual FilterTabs * filterTabs() Q_DECL_OVERRIDE { return fltTabs; } virtual bool getSettings(FilterSettings&) Q_DECL_OVERRIDE; virtual void applySettings(const FilterSettings&) Q_DECL_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, 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/filterbase.h b/krusader/Filter/filterbase.h index b43b42f4..2a1b19ad 100644 --- a/krusader/Filter/filterbase.h +++ b/krusader/Filter/filterbase.h @@ -1,61 +1,51 @@ -/*************************************************************************** - filterbase.h - description - ------------------- - copyright : (C) 2005 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef FILTERBASE_H #define FILTERBASE_H #include "filtersettings.h" // QtCore #include // QtWidgets #include class FilterTabs; class FilterBase { public: virtual ~FilterBase() {} virtual void queryAccepted() = 0; virtual QString name() = 0; virtual FilterTabs * filterTabs() = 0; virtual bool getSettings(FilterSettings&) = 0; virtual void applySettings(const FilterSettings&) = 0; protected: static void setComboBoxValue(QComboBox *cb, QString value) { int idx = cb->findText(value); cb->setCurrentIndex(idx < 0 ? 0 : idx); } }; #endif /* FILTERBASE_H */ diff --git a/krusader/Filter/filterdialog.cpp b/krusader/Filter/filterdialog.cpp index e0cc39ad..68c74f44 100644 --- a/krusader/Filter/filterdialog.cpp +++ b/krusader/Filter/filterdialog.cpp @@ -1,116 +1,106 @@ -/*************************************************************************** - filterdialog.cpp - description - ------------------- - copyright : (C) 2005 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "filterdialog.h" #include "filtertabs.h" #include "generalfilter.h" // QtWidgets #include #include #include #include FilterDialog::FilterDialog(QWidget *parent, QString caption, QStringList extraOptions, bool modal) : QDialog(parent) { setWindowTitle(caption.isNull() ? i18n("Krusader::Choose Files") : caption); setModal(modal); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); QTabWidget *filterWidget = new QTabWidget; filterTabs = FilterTabs::addTo(filterWidget, FilterTabs::HasProfileHandler, extraOptions); generalFilter = static_cast (filterTabs->get("GeneralFilter")); mainLayout->addWidget(filterWidget); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Reset); mainLayout->addWidget(buttonBox); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, SIGNAL(accepted()), SLOT(slotOk())); connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); connect(buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()), SLOT(slotReset())); connect(filterTabs, SIGNAL(closeRequest(bool)), this, SLOT(slotCloseRequest(bool))); generalFilter->searchFor->setFocus(); if(modal) exec(); } void FilterDialog::applySettings(const FilterSettings &s) { filterTabs->applySettings(s); } KRQuery FilterDialog::getQuery() { return settings.toQuery(); } bool FilterDialog::isExtraOptionChecked(QString name) { return filterTabs->isExtraOptionChecked(name); } void FilterDialog::checkExtraOption(QString name, bool check) { filterTabs->checkExtraOption(name, check); } void FilterDialog::slotCloseRequest(bool doAccept) { if (doAccept) { slotOk(); accept(); } else reject(); } void FilterDialog::slotReset() { filterTabs->reset(); generalFilter->searchFor->setFocus(); } void FilterDialog::slotOk() { settings = filterTabs->getSettings(); if(settings.isValid()) accept(); } diff --git a/krusader/Filter/filterdialog.h b/krusader/Filter/filterdialog.h index f0e4dc84..1b8a6c74 100644 --- a/krusader/Filter/filterdialog.h +++ b/krusader/Filter/filterdialog.h @@ -1,69 +1,59 @@ -/*************************************************************************** - filterdialog.h - description - ------------------- - copyright : (C) 2005 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef FILTERDIALOG_H #define FILTERDIALOG_H #include "filtersettings.h" #include "../FileSystem/krquery.h" // QtWidgets #include class FilterTabs; class GeneralFilter; class FilterDialog : public QDialog { Q_OBJECT public: explicit FilterDialog(QWidget *parent = 0, QString caption = QString(), QStringList extraOptions = QStringList(), bool modal = true); KRQuery getQuery(); const FilterSettings& getSettings() { return settings; } void applySettings(const FilterSettings &s); bool isExtraOptionChecked(QString name); void checkExtraOption(QString name, bool check); public slots: void slotCloseRequest(bool doAccept); void slotReset(); void slotOk(); private: FilterTabs * filterTabs; GeneralFilter * generalFilter; FilterSettings settings; }; #endif /* FILTERDIALOG_H */ diff --git a/krusader/Filter/filtersettings.cpp b/krusader/Filter/filtersettings.cpp index d481ac1c..96f8ce34 100644 --- a/krusader/Filter/filtersettings.cpp +++ b/krusader/Filter/filtersettings.cpp @@ -1,337 +1,329 @@ -/*************************************************************************** - filtersettings.cpp - description - ------------------- - copyright : (C) 2003 + by Shie Erlich & Rafi Yanai & Csaba Karai - (C) 2011 + by Jan Lepper - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2011 by Jan Lepper * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "filtersettings.h" #include "../krservices.h" #include #include FilterSettings::FileSize& FilterSettings::FileSize::operator=(const FileSize &other) { amount = other.amount; unit = other.unit; return *this; } KIO::filesize_t FilterSettings::FileSize::size() const { switch (unit) { case Byte: return amount; case KiloByte: return amount * 1024; case MegaByte: return amount * 1024 * 1024; case GigaByte: return amount * 1024 * 1024 * 1024; default: qWarning() << "invalid size unit: " << unit; return amount; } } FilterSettings::TimeSpan& FilterSettings::TimeSpan::operator=(const TimeSpan &other) { amount = other.amount; unit = other.unit; return *this; } int FilterSettings::TimeSpan::days() const { switch (unit) { case Day: return amount; case Week: return amount * 7; case Month: return amount * 30; case Year: return amount * 365; default: qWarning() << "invalid time unit: " << unit; return amount; } } FilterSettings::FilterSettings() : valid(false), searchFor("*"), searchForCase(false), searchInArchives(false), recursive(false), followLinks(false), containsTextCase(false), containsWholeWord(false), containsRegExp(false), minSizeEnabled(false), maxSizeEnabled(false), modifiedBetweenEnabled(false), notModifiedAfterEnabled(false), modifiedInTheLastEnabled(false), ownerEnabled(false), groupEnabled(false), permissionsEnabled(false) { } FilterSettings& FilterSettings::operator=(const FilterSettings& other) { #define COPY(var) { var = other.var; } COPY(valid); COPY(searchFor); COPY(searchForCase); COPY(mimeType); COPY(searchInArchives); COPY(recursive); COPY(followLinks); COPY(searchIn); COPY(dontSearchIn); COPY(excludeFolderNames); COPY(contentEncoding); COPY(containsText); COPY(containsTextCase); COPY(containsWholeWord); COPY(containsRegExp); COPY(minSizeEnabled); COPY(minSize); COPY(maxSizeEnabled); COPY(maxSize); COPY(modifiedBetweenEnabled); COPY(modifiedBetween1); COPY(modifiedBetween2); COPY(notModifiedAfterEnabled); COPY(notModifiedAfter); COPY(modifiedInTheLastEnabled); COPY(modifiedInTheLast); COPY(notModifiedInTheLast); COPY(ownerEnabled); COPY(owner); COPY(groupEnabled); COPY(group); COPY(permissionsEnabled); COPY(permissions); #undef COPY return *this; } void FilterSettings::load(KConfigGroup cfg) { *this = FilterSettings(); #define LOAD(key, var) { var = cfg.readEntry(key, var); } LOAD("IsValid", valid); if(!isValid()) return; LOAD("SearchFor", searchFor); LOAD("MimeType", mimeType); LOAD("SearchInArchives", searchInArchives); LOAD("Recursive", recursive); LOAD("FollowLinks", followLinks); searchIn = KrServices::toUrlList(cfg.readEntry("SearchIn", QStringList())); dontSearchIn = KrServices::toUrlList(cfg.readEntry("DontSearchIn", QStringList())); excludeFolderNames = QStringList(); LOAD("ContentEncoding", contentEncoding); LOAD("ContainsText", containsText); LOAD("ContainsTextCase", containsTextCase); LOAD("ContainsWholeWord", containsWholeWord); LOAD("ContainsRegExp", containsRegExp); LOAD("MinSizeEnabled", minSizeEnabled); LOAD("MinSizeAmount", minSize.amount); minSize.unit = static_cast(cfg.readEntry("MinSizeUnit", 0)); LOAD("MaxSizeEnabled", maxSizeEnabled); LOAD("MaxSizeAmount", maxSize.amount); maxSize.unit = static_cast(cfg.readEntry("MaxSizeUnit", 0)); LOAD("ModifiedBetweenEnabled", modifiedBetweenEnabled); LOAD("ModifiedBetween1", modifiedBetween1); LOAD("ModifiedBetween2", modifiedBetween2); LOAD("NotModifiedAfterEnabled", notModifiedAfterEnabled); LOAD("NotModifiedAfter", notModifiedAfter); LOAD("ModifiedInTheLastEnabled", modifiedInTheLastEnabled); LOAD("ModifiedInTheLastAmount", modifiedInTheLast.amount); modifiedInTheLast.unit = static_cast(cfg.readEntry("ModifiedInTheLastUnit", 0)); LOAD("NotModifiedInTheLastAmount", notModifiedInTheLast.amount); notModifiedInTheLast.unit = static_cast(cfg.readEntry("NotModifiedInTheLastUnit", 0)); LOAD("OwnerEnabled", ownerEnabled); LOAD("Owner", owner); LOAD("GroupEnabled", groupEnabled); LOAD("Group", group); LOAD("PermissionsEnabled", permissionsEnabled); LOAD("Permissions", permissions); #undef LOAD } void FilterSettings::saveDate(QString key, const QDate &date, KConfigGroup &cfg) { if(date.isValid()) cfg.writeEntry(key, date); else cfg.deleteEntry(key); } void FilterSettings::save(KConfigGroup cfg) const { cfg.writeEntry("IsValid", valid); if(!isValid()) return; cfg.writeEntry("SearchFor", searchFor); cfg.writeEntry("MimeType", mimeType); cfg.writeEntry("SearchInArchives", searchInArchives); cfg.writeEntry("Recursive", recursive); cfg.writeEntry("FollowLinks", followLinks); cfg.writeEntry("SearchIn", KrServices::toStringList(searchIn)); cfg.writeEntry("DontSearchIn", KrServices::toStringList(dontSearchIn)); cfg.writeEntry("ContentEncoding", contentEncoding); cfg.writeEntry("ContainsText", containsText); cfg.writeEntry("ContainsTextCase", containsTextCase); cfg.writeEntry("ContainsWholeWord", containsWholeWord); cfg.writeEntry("ContainsRegExp", containsRegExp); cfg.writeEntry("MinSizeEnabled", minSizeEnabled); cfg.writeEntry("MinSizeAmount", minSize.amount); cfg.writeEntry("MinSizeUnit", static_cast(minSize.unit)); cfg.writeEntry("MaxSizeEnabled", maxSizeEnabled); cfg.writeEntry("MaxSizeAmount", maxSize.amount); cfg.writeEntry("MaxSizeUnit", static_cast(maxSize.unit)); cfg.writeEntry("ModifiedBetweenEnabled", modifiedBetweenEnabled); saveDate("ModifiedBetween1", modifiedBetween1, cfg); saveDate("ModifiedBetween2", modifiedBetween2, cfg); cfg.writeEntry("NotModifiedAfterEnabled", notModifiedAfterEnabled); saveDate("NotModifiedAfter", notModifiedAfter, cfg); cfg.writeEntry("ModifiedInTheLastEnabled", modifiedInTheLastEnabled); cfg.writeEntry("ModifiedInTheLastAmount", modifiedInTheLast.amount); cfg.writeEntry("ModifiedInTheLastUnit", static_cast(modifiedInTheLast.unit)); cfg.writeEntry("NotModifiedInTheLastAmount", notModifiedInTheLast.amount); cfg.writeEntry("NotModifiedInTheLastUnit", static_cast(notModifiedInTheLast.unit)); cfg.writeEntry("OwnerEnabled", ownerEnabled); cfg.writeEntry("Owner", owner); cfg.writeEntry("GroupEnabled", groupEnabled); cfg.writeEntry("Group", group); cfg.writeEntry("PermissionsEnabled", permissionsEnabled); cfg.writeEntry("Permissions", permissions); } // bool start: set it to true if this date is the beginning of the search, // if it's the end, set it to false time_t FilterSettings::qdate2time_t (QDate d, bool start) { struct tm t; t.tm_sec = (start ? 0 : 59); t.tm_min = (start ? 0 : 59); t.tm_hour = (start ? 0 : 23); t.tm_mday = d.day(); t.tm_mon = d.month() - 1; t.tm_year = d.year() - 1900; t.tm_wday = d.dayOfWeek() - 1; // actually ignored by mktime t.tm_yday = d.dayOfYear() - 1; // actually ignored by mktime t.tm_isdst = -1; // daylight saving time information isn't available return mktime(&t); } KRQuery FilterSettings::toQuery() const { if(!isValid()) return KRQuery(); KRQuery query; ////////////// General Options ////////////// query.setNameFilter(searchFor, searchForCase); query.setMimeType(mimeType); QString charset; if (!contentEncoding.isEmpty()) charset = KCharsets::charsets()->encodingForName(contentEncoding); if (!containsText.isEmpty()) { query.setContent(containsText, containsTextCase, containsWholeWord, charset, containsRegExp); } query.setRecursive(recursive); query.setSearchInArchives(searchInArchives); query.setFollowLinks(followLinks); if (!searchIn.isEmpty()) query.setSearchInDirs(searchIn); if (!dontSearchIn.isEmpty()) query.setDontSearchInDirs(dontSearchIn); query.setExcludeFolderNames(excludeFolderNames); ////////////// Advanced Options ////////////// if (minSizeEnabled) query.setMinimumFileSize(minSize.size()); if (maxSizeEnabled) query.setMaximumFileSize(maxSize.size()); if (modifiedBetweenEnabled) { if(modifiedBetween1.isValid()) query.setNewerThan(qdate2time_t(modifiedBetween1, true)); if(modifiedBetween2.isValid()) query.setOlderThan(qdate2time_t(modifiedBetween2, false)); } else if (notModifiedAfterEnabled && notModifiedAfter.isValid()) { query.setOlderThan(qdate2time_t(notModifiedAfter, false)); } else if (modifiedInTheLastEnabled) { if (modifiedInTheLast.amount) { QDate d = QDate::currentDate().addDays((-1) * modifiedInTheLast.days()); query.setNewerThan(qdate2time_t(d, true)); } if (notModifiedInTheLast.amount) { QDate d = QDate::currentDate().addDays((-1) * notModifiedInTheLast.days()); query.setOlderThan(qdate2time_t(d, true)); } } if (ownerEnabled && !owner.isEmpty()) query.setOwner(owner); if (groupEnabled && !group.isEmpty()) query.setGroup(group); if (permissionsEnabled && !permissions.isEmpty()) query.setPermissions(permissions); return query; } diff --git a/krusader/Filter/filtersettings.h b/krusader/Filter/filtersettings.h index e15449a7..b7fc947e 100644 --- a/krusader/Filter/filtersettings.h +++ b/krusader/Filter/filtersettings.h @@ -1,127 +1,117 @@ -/*************************************************************************** - filtersettings.h - description - ------------------- - copyright : (C) 2011 + by Jan Lepper - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2011 Jan Lepper * + * Copyright (C) 2011-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef FILTERSETTINGS_H #define FILTERSETTINGS_H #include "../FileSystem/krquery.h" #include class FilterSettings { friend class FilterTabs; friend class GeneralFilter; friend class AdvancedFilter; public: FilterSettings(); FilterSettings& operator=(const FilterSettings& other); bool isValid() const { return valid; } void load(KConfigGroup cfg); void save(KConfigGroup cfg) const; KRQuery toQuery() const; private: enum SizeUnit { Byte = 0, KiloByte, MegaByte, GigaByte }; enum TimeUnit { Day = 0, Week, Month, Year }; class FileSize { public: FileSize() : amount(0), unit(Byte) {} FileSize& operator=(const FileSize &other); KIO::filesize_t size() const; KIO::filesize_t amount; SizeUnit unit; }; class TimeSpan { public: TimeSpan() : amount(0), unit(Day) {} TimeSpan& operator=(const TimeSpan &other); int days() const; int amount; TimeUnit unit; }; static void saveDate(QString key, const QDate &date, KConfigGroup &cfg); static time_t qdate2time_t(QDate d, bool start); bool valid; QString searchFor; bool searchForCase; QString mimeType; bool searchInArchives; bool recursive; bool followLinks; QList searchIn; QList dontSearchIn; QStringList excludeFolderNames; QString contentEncoding; QString containsText; bool containsTextCase; bool containsWholeWord; bool containsRegExp; bool minSizeEnabled; FileSize minSize; bool maxSizeEnabled; FileSize maxSize; bool modifiedBetweenEnabled; QDate modifiedBetween1; QDate modifiedBetween2; bool notModifiedAfterEnabled; QDate notModifiedAfter; bool modifiedInTheLastEnabled; TimeSpan modifiedInTheLast; TimeSpan notModifiedInTheLast; bool ownerEnabled; QString owner; bool groupEnabled; QString group; bool permissionsEnabled; QString permissions; }; #endif //FILTERSETTINGS_H diff --git a/krusader/Filter/filtertabs.cpp b/krusader/Filter/filtertabs.cpp index ef917da1..585a3dde 100644 --- a/krusader/Filter/filtertabs.cpp +++ b/krusader/Filter/filtertabs.cpp @@ -1,165 +1,155 @@ -/*************************************************************************** - filtertab.cpp - description - ------------------- - copyright : (C) 2005 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "filtertabs.h" #include "filterdialog.h" #include "generalfilter.h" #include "advancedfilter.h" #include "../krglobal.h" // QtWidgets #include #include #include #include FilterTabs::FilterTabs(int properties, QTabWidget *tabWidget, QObject *parent, QStringList extraOptions) : QObject(parent) { this->tabWidget = tabWidget; GeneralFilter *generalFilter = new GeneralFilter(this, properties, tabWidget, extraOptions); tabWidget->addTab(generalFilter, i18n("&General")); filterList.append(generalFilter); pageNumbers.append(tabWidget->indexOf(generalFilter)); AdvancedFilter *advancedFilter = new AdvancedFilter(this, tabWidget); tabWidget->addTab(advancedFilter, i18n("&Advanced")); filterList.append(advancedFilter); pageNumbers.append(tabWidget->indexOf(advancedFilter)); reset(); // apply defaults } bool FilterTabs::isExtraOptionChecked(QString name) { return static_cast(get("GeneralFilter"))->isExtraOptionChecked(name); } void FilterTabs::checkExtraOption(QString name, bool check) { static_cast(get("GeneralFilter"))->checkExtraOption(name, check); } FilterTabs * FilterTabs::addTo(QTabWidget *tabWidget, int props, QStringList extraOptions) { return new FilterTabs(props, tabWidget, tabWidget, extraOptions); } FilterSettings FilterTabs::getSettings() { FilterSettings s; for (int i = 0; i != filterList.count(); i++) { if(!filterList[i]->getSettings(s)) { tabWidget->setCurrentIndex(pageNumbers[i]); return FilterSettings(); } } s.valid = true; acceptQuery(); return s; } void FilterTabs::applySettings(const FilterSettings &s) { if(s.isValid()) { QListIterator it(filterList); while (it.hasNext()) it.next()->applySettings(s); } } void FilterTabs::reset() { FilterSettings s; // default settings s.valid = true; applySettings(s); } void FilterTabs::saveToProfile(QString name) { FilterSettings s(getSettings()); if(s.isValid()) s.save(KConfigGroup(krConfig, name)); krConfig->sync(); } void FilterTabs::loadFromProfile(QString name) { FilterSettings s; s.load(KConfigGroup(krConfig, name)); if(!s.isValid()) KMessageBox::error(tabWidget, i18n("Could not load profile.")); else applySettings(s); } void FilterTabs::acceptQuery() { QListIterator it(filterList); while (it.hasNext()) { FilterBase *filter = it.next(); filter->queryAccepted(); } } bool FilterTabs::fillQuery(KRQuery *query) { *query = getSettings().toQuery(); return !query->isNull(); } FilterBase * FilterTabs::get(QString name) { QListIterator it(filterList); while (it.hasNext()) { FilterBase *filter = it.next(); if (filter->name() == name) return filter; } return 0; } KRQuery FilterTabs::getQuery(QWidget *parent) { FilterDialog dialog(parent); return dialog.getQuery(); } diff --git a/krusader/Filter/filtertabs.h b/krusader/Filter/filtertabs.h index 1559fefa..4774a22d 100644 --- a/krusader/Filter/filtertabs.h +++ b/krusader/Filter/filtertabs.h @@ -1,88 +1,78 @@ -/*************************************************************************** - filtertab.h - description - ------------------- - copyright : (C) 2005 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef FILTERTABS_H #define FILTERTABS_H // QtCore #include #include "filterbase.h" class QTabWidget; class FilterTabs : public QObject { Q_OBJECT public: enum { HasProfileHandler = 0x1000, HasRecurseOptions = 0x2000, HasSearchIn = 0x4000, HasDontSearchIn = 0x8000, Default = 0xe000 }; static FilterTabs * addTo(QTabWidget *tabWidget, int props = FilterTabs::Default, QStringList extraOptions = QStringList()); static KRQuery getQuery(QWidget *parent = 0); FilterBase *get(QString name); bool isExtraOptionChecked(QString name); void checkExtraOption(QString name, bool check); FilterSettings getSettings(); void applySettings(const FilterSettings &s); void reset(); public slots: void loadFromProfile(QString); void saveToProfile(QString); bool fillQuery(KRQuery *query); void close(bool accept = true) { emit closeRequest(accept); } signals: void closeRequest(bool accept = true); private: FilterTabs(int properties, QTabWidget *tabWidget, QObject *parent, QStringList extraOptions); void acceptQuery(); QList filterList; QList pageNumbers; QTabWidget * tabWidget; }; #endif /* FILTERTABS_H */ diff --git a/krusader/Filter/generalfilter.cpp b/krusader/Filter/generalfilter.cpp index 389b6adc..e2eb0f6b 100644 --- a/krusader/Filter/generalfilter.cpp +++ b/krusader/Filter/generalfilter.cpp @@ -1,644 +1,636 @@ -/*************************************************************************** - generalfilter.cpp - description - ------------------- - copyright : (C) 2003 + by Shie Erlich & Rafi Yanai & Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Shie Erlich * + * Copyright (C) 2003 Rafi Yanai * + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "generalfilter.h" #include "filtertabs.h" #include "../krglobal.h" #include "../krservices.h" #include "../FileSystem/filesystem.h" // QtWidgets #include #include #include #include #include #include #include #include #include #include #include typedef struct { const char *description; const char *regExp; int cursorAdjustment; } term; static const term items[] = { { I18N_NOOP("Any Character"), ".", 0 }, { I18N_NOOP("Start of Line"), "^", 0 }, { I18N_NOOP("End of Line"), "$", 0 }, { I18N_NOOP("Set of Characters"), "[]", -1 }, { I18N_NOOP("Repeats, Zero or More Times"), "*", 0 }, { I18N_NOOP("Repeats, One or More Times"), "+", 0 }, { I18N_NOOP("Optional"), "?", 0 }, { I18N_NOOP("Escape"), "\\", 0 }, { I18N_NOOP("TAB"), "\\t", 0 }, { I18N_NOOP("Newline"), "\\n", 0 }, { I18N_NOOP("Carriage Return"), "\\r", 0 }, { I18N_NOOP("White Space"), "\\s", 0 }, { I18N_NOOP("Digit"), "\\d", 0 }, }; class RegExpAction : public QAction { public: RegExpAction(QObject *parent, const QString &text, const QString ®Exp, int cursor) : QAction(text, parent), mText(text), mRegExp(regExp), mCursor(cursor) { } QString text() const { return mText; } QString regExp() const { return mRegExp; } int cursor() const { return mCursor; } private: QString mText; QString mRegExp; int mCursor; }; GeneralFilter::GeneralFilter(FilterTabs *tabs, int properties, QWidget *parent, QStringList extraOptions) : QWidget(parent), profileManager(0), fltTabs(tabs) { QGridLayout *filterLayout = new QGridLayout(this); filterLayout->setSpacing(6); filterLayout->setContentsMargins(11, 11, 11, 11); this->properties = properties; // Options for name filtering QGroupBox *nameGroup = new QGroupBox(this); nameGroup->setTitle(i18n("File Name")); QGridLayout *nameGroupLayout = new QGridLayout(nameGroup); nameGroupLayout->setAlignment(Qt::AlignTop); nameGroupLayout->setSpacing(6); nameGroupLayout->setContentsMargins(11, 11, 11, 11); searchForCase = new QCheckBox(nameGroup); searchForCase->setText(i18n("&Case sensitive")); searchForCase->setChecked(false); nameGroupLayout->addWidget(searchForCase, 1, 2); QLabel *searchForLabel = new QLabel(nameGroup); searchForLabel->setText(i18n("Search &for:")); nameGroupLayout->addWidget(searchForLabel, 0, 0); searchFor = new KHistoryComboBox(false, nameGroup/*, "searchFor"*/); QSizePolicy searchForPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); searchForPolicy.setHeightForWidth(searchFor->sizePolicy().hasHeightForWidth()); searchFor->setSizePolicy(searchForPolicy); searchFor->setEditable(true); searchFor->setDuplicatesEnabled(false); searchFor->setMaxCount(25); searchFor->setMinimumContentsLength(10); searchForLabel->setBuddy(searchFor); nameGroupLayout->addWidget(searchFor, 0, 1, 1, 2); QString s = "

" + i18n("

The filename filtering criteria is defined here.

You can make use of wildcards. Multiple patterns are separated by space (means logical OR) and patterns are excluded from the search using the pipe symbol.

If the pattern is ended with a slash (*pattern*/), that means that pattern relates to recursive search of folders.

  • pattern - means to search those files/folders that name is pattern, recursive search goes through all subfolders independently of the value of pattern
  • pattern/ - means to search all files/folders, but recursive search goes through/excludes the folders that name is pattern

It is allowed to use quotation marks for names that contain space. Filter \"Program Files\" searches out those files/folders that name is Program Files.

Examples:

  • *.o
  • *.h *.c\?\?
  • *.cpp *.h | *.moc.cpp
  • * | .svn/ .git/

Note: the search term 'text' is equivalent to '*text*'.

"); searchFor->setWhatsThis(s); searchForLabel->setWhatsThis(s); QLabel *searchType = new QLabel(nameGroup); searchType->setText(i18n("&Of type:")); nameGroupLayout->addWidget(searchType, 1, 0); ofType = new KComboBox(false, nameGroup); ofType->setObjectName("ofType"); QSizePolicy ofTypePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); ofTypePolicy.setHeightForWidth(ofType->sizePolicy().hasHeightForWidth()); ofType->setSizePolicy(ofTypePolicy); ofType->setEditable(false); searchType->setBuddy(ofType); ofType->addItem(i18n("All Files")); ofType->addItem(i18n("Archives")); ofType->addItem(i18n("Folders")); ofType->addItem(i18n("Image Files")); ofType->addItem(i18n("Text Files")); ofType->addItem(i18n("Video Files")); ofType->addItem(i18n("Audio Files")); connect(ofType, SIGNAL(currentIndexChanged(int)), this, SLOT(slotDisable())); nameGroupLayout->addWidget(ofType, 1, 1); filterLayout->addWidget(nameGroup, 0, 0); middleLayout = new QHBoxLayout(); middleLayout->setSpacing(6); middleLayout->setContentsMargins(0, 0, 0, 0); QSpacerItem* middleSpacer = new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Fixed); middleLayout->addItem(middleSpacer); if (properties & FilterTabs::HasProfileHandler) { // The profile handler QGroupBox *profileHandler = new QGroupBox(this); profileHandler->setTitle(i18n("&Profile handler")); QGridLayout *profileLayout = new QGridLayout(profileHandler); profileLayout->setAlignment(Qt::AlignTop); profileLayout->setSpacing(6); profileLayout->setContentsMargins(11, 11, 11, 11); profileListBox = new KrListWidget(profileHandler); profileLayout->addWidget(profileListBox, 0, 0, 4, 1); profileAddBtn = new QPushButton(profileHandler); KStandardGuiItem::assign(profileAddBtn, KStandardGuiItem::Add); profileLayout->addWidget(profileAddBtn, 0, 1); profileLoadBtn = new QPushButton(i18n("&Load"), profileHandler); profileLoadBtn->setEnabled(false); profileLayout->addWidget(profileLoadBtn, 1, 1); profileOverwriteBtn = new QPushButton(profileHandler); profileOverwriteBtn->setEnabled(false); KStandardGuiItem::assign(profileOverwriteBtn, KStandardGuiItem::Overwrite); profileLayout->addWidget(profileOverwriteBtn, 2, 1); profileRemoveBtn = new QPushButton(profileHandler); profileRemoveBtn->setEnabled(false); KStandardGuiItem::assign(profileRemoveBtn, KStandardGuiItem::Remove); profileLayout->addWidget(profileRemoveBtn, 3, 1); profileManager = new ProfileManager("SelectionProfile", this); profileManager->hide(); middleLayout->addWidget(profileHandler); refreshProfileListBox(); } if (properties & FilterTabs::HasSearchIn) { // Options for search in QGroupBox *searchInGroup = new QGroupBox(this); searchInGroup->setTitle(i18n("Searc&h in")); QGridLayout *searchInLayout = new QGridLayout(searchInGroup); searchInLayout->setAlignment(Qt::AlignTop); searchInLayout->setSpacing(6); searchInLayout->setContentsMargins(11, 11, 11, 11); searchIn = new KURLListRequester(KURLListRequester::RequestDirs, searchInGroup); searchInLayout->addWidget(searchIn, 0, 0); connect(searchIn, SIGNAL(changed()), this, SLOT(slotDisable())); middleLayout->addWidget(searchInGroup); } if (properties & FilterTabs::HasDontSearchIn) { // Options for don't search in QGroupBox *dontSearchInGroup = new QGroupBox(this); dontSearchInGroup->setTitle(i18n("&Do not search in")); QGridLayout *dontSearchInLayout = new QGridLayout(dontSearchInGroup); dontSearchInLayout->setAlignment(Qt::AlignTop); dontSearchInLayout->setSpacing(6); dontSearchInLayout->setContentsMargins(11, 11, 11, 11); dontSearchIn = new KURLListRequester(KURLListRequester::RequestDirs, dontSearchInGroup); dontSearchInLayout->addWidget(dontSearchIn, 0, 0, 1, 2); if (properties & FilterTabs::HasRecurseOptions) { KConfigGroup group(krConfig, "Search"); useExcludeFolderNames = new QCheckBox(this); useExcludeFolderNames->setText(i18n("Exclude Folder Names")); useExcludeFolderNames->setToolTip(i18n("Filters out specified directory names from the results.")); useExcludeFolderNames->setChecked(static_cast(group.readEntry("ExcludeFolderNamesUse", 0))); dontSearchInLayout->addWidget(useExcludeFolderNames, 1, 0, 1, 1); excludeFolderNames = new KHistoryComboBox(false, dontSearchInGroup); QSizePolicy excludeFolderNamesPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); excludeFolderNamesPolicy.setHeightForWidth(excludeFolderNames->sizePolicy().hasHeightForWidth()); excludeFolderNames->setSizePolicy(excludeFolderNamesPolicy); excludeFolderNames->setEditable(true); excludeFolderNames->setDuplicatesEnabled(false); excludeFolderNames->setMaxCount(25); excludeFolderNames->setMinimumContentsLength(10); excludeFolderNames->lineEdit()->setPlaceholderText(i18n("Enter space-separated folder names")); excludeFolderNames->lineEdit()->setWhatsThis(i18n("You can insert names with escaped spaces or quoted.\nExample: .git \"target build\" build\\ krusader")); dontSearchInLayout->addWidget(excludeFolderNames, 1, 1, 1, 1); excludeFolderNames->setHistoryItems(group.readEntry("ExcludeFolderNamesHistory", QStringList())); excludeFolderNames->setEditText(group.readEntry("ExcludeFolderNames", "")); if (!useExcludeFolderNames->isChecked()) { excludeFolderNames->setDisabled(true); } connect(useExcludeFolderNames, &QCheckBox::toggled, excludeFolderNames, &KHistoryComboBox::setEnabled); } middleLayout->addWidget(dontSearchInGroup); } filterLayout->addLayout(middleLayout, 1, 0); // Options for containing text QGroupBox *containsGroup = new QGroupBox(this); containsGroup->setTitle(i18n("Containing text")); QGridLayout *containsLayout = new QGridLayout(containsGroup); containsLayout->setAlignment(Qt::AlignTop); containsLayout->setSpacing(6); containsLayout->setContentsMargins(11, 11, 11, 11); QHBoxLayout *containsTextLayout = new QHBoxLayout(); containsTextLayout->setSpacing(6); containsTextLayout->setContentsMargins(0, 0, 0, 0); containsLabel = new QLabel(containsGroup); QSizePolicy containsLabelPolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); containsLabelPolicy.setHeightForWidth(containsLabel->sizePolicy().hasHeightForWidth()); containsLabel->setSizePolicy(containsLabelPolicy); containsLabel->setText(i18n("&Text:")); containsTextLayout->addWidget(containsLabel); containsText = new KHistoryComboBox(false, containsGroup/*, "containsText"*/); QSizePolicy containsTextPolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); containsTextPolicy.setHeightForWidth(containsText->sizePolicy().hasHeightForWidth()); containsText->setSizePolicy(containsTextPolicy); containsText->setDuplicatesEnabled(false); containsText->setMaxCount(25); containsText->setMinimumContentsLength(10); containsTextLayout->addWidget(containsText); containsLabel->setBuddy(containsText); containsRegExp = new QToolButton(containsGroup); containsRegExp->setPopupMode(QToolButton::MenuButtonPopup); containsRegExp->setCheckable(true); containsRegExp->setText(i18n("RegExp")); // Populate the popup menu. QMenu *patterns = new QMenu(containsRegExp); for (int i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++) { patterns->addAction(new RegExpAction(patterns, i18n(items[i].description), items[i].regExp, items[i].cursorAdjustment)); } connect(containsRegExp, SIGNAL(toggled(bool)), this, SLOT(slotDisable())); connect(containsRegExp, SIGNAL(triggered(QAction*)), this, SLOT(slotRegExpTriggered(QAction*))); containsRegExp->setMenu(patterns); patterns->setEnabled(false); containsTextLayout->addWidget(containsRegExp); containsLayout->addLayout(containsTextLayout, 0, 0); QHBoxLayout *containsCbsLayout = new QHBoxLayout(); containsCbsLayout->setSpacing(6); containsCbsLayout->setContentsMargins(0, 0, 0, 0); encLabel = new QLabel(i18n("Encoding:"), containsGroup); containsCbsLayout->addWidget(encLabel); contentEncoding = new KComboBox(containsGroup); contentEncoding->setEditable(false); contentEncoding->addItem(i18nc("Default encoding", "Default")); contentEncoding->addItems(KCharsets::charsets()->descriptiveEncodingNames()); containsCbsLayout->addWidget(contentEncoding); QSpacerItem* cbSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); containsCbsLayout->addItem(cbSpacer); containsWholeWord = new QCheckBox(containsGroup); QSizePolicy containsWholeWordPolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); containsWholeWordPolicy.setHeightForWidth(containsWholeWord->sizePolicy().hasHeightForWidth()); containsWholeWord->setSizePolicy(containsWholeWordPolicy); containsWholeWord->setText(i18n("&Match whole word only")); containsWholeWord->setChecked(false); containsCbsLayout->addWidget(containsWholeWord); containsTextCase = new QCheckBox(containsGroup); QSizePolicy containsTextCasePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); containsTextCasePolicy.setHeightForWidth(containsTextCase->sizePolicy().hasHeightForWidth()); containsTextCase->setSizePolicy(containsTextCasePolicy); containsTextCase->setText(i18n("Cas&e sensitive")); containsTextCase->setChecked(true); containsCbsLayout->addWidget(containsTextCase); containsLayout->addLayout(containsCbsLayout, 1, 0); filterLayout->addWidget(containsGroup, 2, 0); QHBoxLayout *recurseLayout = new QHBoxLayout(); recurseLayout->setSpacing(6); recurseLayout->setContentsMargins(0, 0, 0, 0); QSpacerItem* recurseSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); recurseLayout->addItem(recurseSpacer); if (properties & FilterTabs::HasRecurseOptions) { // Options for recursive searching searchInDirs = new QCheckBox(this); searchInDirs->setText(i18n("Search in s&ub folders")); searchInDirs->setChecked(true); recurseLayout->addWidget(searchInDirs); searchInArchives = new QCheckBox(this); searchInArchives->setText(i18n("Search in arch&ives")); recurseLayout->addWidget(searchInArchives); followLinks = new QCheckBox(this); followLinks->setText(i18n("Follow &links")); recurseLayout->addWidget(followLinks); } filterLayout->addLayout(recurseLayout, 3, 0); for(int i = 0; i < extraOptions.length(); i++) { QCheckBox *option = new QCheckBox(this); option->setText(extraOptions[i]); recurseLayout->addWidget(option); this->extraOptions.insert(extraOptions[i], option); } // Connection table if (properties & FilterTabs::HasProfileHandler) { connect(profileAddBtn, SIGNAL(clicked()) , this, SLOT(slotAddBtnClicked())); connect(profileLoadBtn, SIGNAL(clicked()) , this, SLOT(slotLoadBtnClicked())); connect(profileOverwriteBtn, SIGNAL(clicked()) , this, SLOT(slotOverwriteBtnClicked())); connect(profileRemoveBtn, SIGNAL(clicked()) , this, SLOT(slotRemoveBtnClicked())); connect(profileListBox, SIGNAL(itemDoubleClicked(QListWidgetItem*)) , this, SLOT(slotProfileDoubleClicked(QListWidgetItem*))); connect(profileManager, SIGNAL(loadFromProfile(QString)), fltTabs, SLOT(loadFromProfile(QString))); connect(profileManager, SIGNAL(saveToProfile(QString)), fltTabs, SLOT(saveToProfile(QString))); } connect(searchFor, SIGNAL(activated(QString)), searchFor, SLOT(addToHistory(QString))); connect(containsText, SIGNAL(activated(QString)), containsText, SLOT(addToHistory(QString))); // load the completion and history lists // ==> search for KConfigGroup group(krConfig, "Search"); QStringList list = group.readEntry("SearchFor Completion", QStringList()); searchFor->completionObject()->setItems(list); list = group.readEntry("SearchFor History", QStringList()); searchFor->setHistoryItems(list); // ==> grep list = group.readEntry("ContainsText Completion", QStringList()); containsText->completionObject()->setItems(list); list = group.readEntry("ContainsText History", QStringList()); containsText->setHistoryItems(list); setTabOrder(searchFor, containsText); // search for -> content setTabOrder(containsText, searchType); // content -> search type slotDisable(); } GeneralFilter::~GeneralFilter() { // save the history combos // ==> search for QStringList list = searchFor->completionObject()->items(); KConfigGroup group(krConfig, "Search"); group.writeEntry("SearchFor Completion", list); list = searchFor->historyItems(); group.writeEntry("SearchFor History", list); // ==> grep text list = containsText->completionObject()->items(); group.writeEntry("ContainsText Completion", list); list = containsText->historyItems(); group.writeEntry("ContainsText History", list); if ((properties & FilterTabs::HasDontSearchIn) && (properties & FilterTabs::HasRecurseOptions)) { list = excludeFolderNames->historyItems(); group.writeEntry("ExcludeFolderNamesHistory", list); group.writeEntry("ExcludeFolderNames", excludeFolderNames->currentText()); group.writeEntry("ExcludeFolderNamesUse", static_cast(useExcludeFolderNames->checkState())); } krConfig->sync(); } bool GeneralFilter::isExtraOptionChecked(QString name) { QCheckBox *option = extraOptions[name]; return option ? option->isChecked() : false; } void GeneralFilter::checkExtraOption(QString name, bool check) { QCheckBox *option = extraOptions[name]; if (option) option->setChecked(check); } void GeneralFilter::queryAccepted() { searchFor->addToHistory(searchFor->currentText()); containsText->addToHistory(containsText->currentText()); if ((properties & FilterTabs::HasDontSearchIn) && (properties & FilterTabs::HasRecurseOptions)) { excludeFolderNames->addToHistory(excludeFolderNames->currentText()); } } void GeneralFilter::refreshProfileListBox() { profileListBox->clear(); profileListBox->addItems(ProfileManager::availableProfiles("SelectionProfile")); if (profileListBox->count() != 0) { profileLoadBtn->setEnabled(true); profileOverwriteBtn->setEnabled(true); profileRemoveBtn->setEnabled(true); } else { profileLoadBtn->setEnabled(false); profileOverwriteBtn->setEnabled(false); profileRemoveBtn->setEnabled(false); } } void GeneralFilter::slotAddBtnClicked() { profileManager->newProfile(searchFor->currentText().simplified()); refreshProfileListBox(); } void GeneralFilter::slotOverwriteBtnClicked() { QListWidgetItem *item = profileListBox->currentItem(); if (item != 0) profileManager->overwriteProfile(item->text()); } void GeneralFilter::slotRemoveBtnClicked() { QListWidgetItem *item = profileListBox->currentItem(); if (item != 0) { profileManager->deleteProfile(item->text()); refreshProfileListBox(); } } void GeneralFilter::slotProfileDoubleClicked(QListWidgetItem *item) { if (item != 0) { QString profileName = item->text(); profileManager->loadProfile(profileName); fltTabs->close(true); } } void GeneralFilter::slotLoadBtnClicked() { QListWidgetItem *item = profileListBox->currentItem(); if (item != 0) profileManager->loadProfile(item->text()); } void GeneralFilter::slotDisable() { bool state = containsRegExp->isChecked(); bool global = ofType->currentText() != i18n("Folders"); bool remoteOnly = false; if (properties & FilterTabs::HasSearchIn) { QList urlList = searchIn->urlList(); remoteOnly = urlList.count() != 0; foreach(const QUrl &url, urlList) if (url.scheme() == "file") remoteOnly = false; } containsWholeWord->setEnabled(!state && global); containsRegExp->menu()->setEnabled(state && global); encLabel->setEnabled(global); contentEncoding->setEnabled(global); containsTextCase->setEnabled(global); containsRegExp->setEnabled(global); if (properties & FilterTabs::HasRecurseOptions) searchInArchives->setEnabled(global && !remoteOnly); containsLabel->setEnabled(global); containsText->setEnabled(global); } void GeneralFilter::slotRegExpTriggered(QAction * act) { if (act == 0) return; RegExpAction *regAct = dynamic_cast(act); if (regAct == 0) return; containsText->lineEdit()->insert(regAct->regExp()); containsText->lineEdit()->setCursorPosition(containsText->lineEdit()->cursorPosition() + regAct->cursor()); containsText->lineEdit()->setFocus(); } bool GeneralFilter::getSettings(FilterSettings &s) { // check that we have (at least) what to search, and where to search in if (searchFor->currentText().simplified().isEmpty()) { KMessageBox::error(this , i18n("No search criteria entered.")); searchFor->setFocus(); return false; } s.searchFor = searchFor->currentText().trimmed(); s.searchForCase = searchForCase->isChecked(); if (ofType->currentText() != i18n("All Files")) s.mimeType = ofType->currentText(); if (containsText->isEnabled()) { s.containsText = containsText->currentText(); s.containsTextCase = containsTextCase->isChecked(); s.containsWholeWord = containsWholeWord->isChecked(); s.containsRegExp = containsRegExp->isChecked(); } if (contentEncoding->currentIndex() != 0) s.contentEncoding = KCharsets::charsets()->encodingForName(contentEncoding->currentText()); if (properties & FilterTabs::HasRecurseOptions) { s.recursive = searchInDirs->isChecked(); s.searchInArchives = searchInArchives->isChecked(); s.followLinks = followLinks->isChecked(); } if (properties & FilterTabs::HasSearchIn) { s.searchIn = searchIn->urlList(); if (s.searchIn.isEmpty()) { // we need a place to search in KMessageBox::error(this , i18n("Please specify a location to search in.")); searchIn->lineEdit()->setFocus(); return false; } } if (properties & FilterTabs::HasDontSearchIn) { s.dontSearchIn = dontSearchIn->urlList(); if (properties & FilterTabs::HasRecurseOptions) { if (useExcludeFolderNames->isChecked()) { s.excludeFolderNames = KShell::splitArgs(excludeFolderNames->currentText()); } else { s.excludeFolderNames = QStringList(); } } } return true; } void GeneralFilter::applySettings(const FilterSettings &s) { searchFor->setEditText(s.searchFor); searchForCase->setChecked(s.searchForCase); setComboBoxValue(ofType, s.mimeType); containsText->setEditText(s.containsText); containsTextCase->setChecked(s.containsTextCase); containsWholeWord->setChecked(s.containsWholeWord); containsRegExp->setChecked(s.containsRegExp); setComboBoxValue(contentEncoding, KCharsets::charsets()->descriptionForEncoding(s.contentEncoding)); if (properties & FilterTabs::HasRecurseOptions) { searchInDirs->setChecked(s.recursive); searchInArchives->setChecked(s.searchInArchives); followLinks->setChecked(s.followLinks); } if (properties & FilterTabs::HasSearchIn) { searchIn->lineEdit()->clear(); searchIn->listBox()->clear(); searchIn->listBox()->addItems(KrServices::toStringList(s.searchIn)); } if (properties & FilterTabs::HasDontSearchIn) { dontSearchIn->lineEdit()->clear(); dontSearchIn->listBox()->clear(); dontSearchIn->listBox()->addItems(KrServices::toStringList(s.dontSearchIn)); } } diff --git a/krusader/Filter/generalfilter.h b/krusader/Filter/generalfilter.h index bbb71aa3..657faf5c 100644 --- a/krusader/Filter/generalfilter.h +++ b/krusader/Filter/generalfilter.h @@ -1,125 +1,115 @@ -/*************************************************************************** - generalfilter.h - description - ------------------- - copyright : (C) 2003 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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" class GeneralFilter : public QWidget, public FilterBase { Q_OBJECT public: GeneralFilter(FilterTabs *tabs, int properties, QWidget *parent = 0, QStringList extraOptions = QStringList()); ~GeneralFilter(); virtual void queryAccepted() Q_DECL_OVERRIDE; virtual QString name() Q_DECL_OVERRIDE { return "GeneralFilter"; } virtual FilterTabs * filterTabs() Q_DECL_OVERRIDE { return fltTabs; } virtual bool getSettings(FilterSettings&) Q_DECL_OVERRIDE; virtual void applySettings(const FilterSettings&) Q_DECL_OVERRIDE; bool isExtraOptionChecked(QString name); void checkExtraOption(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; QHBoxLayout *middleLayout; KHistoryComboBox* 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; }; #endif /* GENERALFILTER_H */ diff --git a/krusader/GUI/kcmdline.cpp b/krusader/GUI/kcmdline.cpp index 4cd20045..add559b6 100644 --- a/krusader/GUI/kcmdline.cpp +++ b/krusader/GUI/kcmdline.cpp @@ -1,325 +1,316 @@ -/*************************************************************************** - kcmdline.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kcmdline.h" // QtCore #include #include #include // QtGui #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include "../krglobal.h" #include "../kicons.h" #include "../krslots.h" #include "../defaults.h" #include "../krusaderview.h" #include "../krservices.h" #include "../ActionMan/addplaceholderpopup.h" #include "kcmdmodebutton.h" CmdLineCombo::CmdLineCombo(QWidget *parent) : KHistoryComboBox(parent), _handlingLineEditResize(false) { lineEdit()->installEventFilter(this); _pathLabel = new QLabel(this); _pathLabel->setWhatsThis(i18n("Name of folder where command will be processed.")); _pathLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); } bool CmdLineCombo::eventFilter(QObject *watched, QEvent *e) { if(watched == lineEdit() && (e->type() == QEvent::Move || e->type() == QEvent::Resize)) { if(!_handlingLineEditResize) { // avoid infinite recursion _handlingLineEditResize = true; updateLineEditGeometry(); _handlingLineEditResize = false; } } return false; } void CmdLineCombo::setPath(QString path) { _path = path; doLayout(); } void CmdLineCombo::updateLineEditGeometry() { QRect r = lineEdit()->geometry(); r.setLeft(_pathLabel->geometry().right()); lineEdit()->setGeometry(r); } void CmdLineCombo::doLayout() { QString pathNameLabel = _path; QFontMetrics fm(_pathLabel->fontMetrics()); int textWidth = fm.width(_path); int maxWidth = (width() + _pathLabel->width()) * 2 / 5; int letters = _path.length() / 2; while (letters && textWidth > maxWidth) { pathNameLabel = _path.left(letters) + "..." + _path.right(letters); letters--; textWidth = fm.width(pathNameLabel); } _pathLabel->setText(pathNameLabel + "> "); _pathLabel->adjustSize(); QStyleOptionComboBox opt; initStyleOption(&opt); QRect labelRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); labelRect.adjust(2, 0, 0, 0); labelRect.setWidth(_pathLabel->width()); _pathLabel->setGeometry(labelRect); updateLineEditGeometry(); } void CmdLineCombo::resizeEvent(QResizeEvent *e) { KHistoryComboBox::resizeEvent(e); doLayout(); } void CmdLineCombo::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Enter: case Qt::Key_Return: if (e->modifiers() & Qt::ControlModifier) { SLOTS->insertFileName((e->modifiers()&Qt::ShiftModifier)!=0); break; } KHistoryComboBox::keyPressEvent(e); break; case Qt::Key_Down: if (e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { MAIN_VIEW->focusTerminalEmulator(); return; } else KHistoryComboBox::keyPressEvent(e); break; case Qt::Key_Up: if (e->modifiers() == Qt::ControlModifier || e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { emit returnToPanel(); return; } else KHistoryComboBox::keyPressEvent(e); break; case Qt::Key_Escape: if (e->modifiers() == 0) { emit returnToPanel(); return; } else KHistoryComboBox::keyPressEvent(e); break; default: KHistoryComboBox::keyPressEvent(e); } } KCMDLine::KCMDLine(QWidget *parent) : QWidget(parent) { QGridLayout * layout = new QGridLayout(this); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); int height = QFontMetrics(QFontDatabase::systemFont(QFontDatabase::GeneralFont)).height(); height = height + 5 * (height > 14) + 6; // and editable command line completion.setMode(KUrlCompletion::FileCompletion); cmdLine = new CmdLineCombo(this); cmdLine->setMaxCount(100); // remember 100 commands cmdLine->setMinimumContentsLength(10); cmdLine->setDuplicatesEnabled(false); cmdLine->setMaximumHeight(height); cmdLine->setCompletionObject(&completion); cmdLine->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); // load the history KConfigGroup grpSvr(krConfig, "Private"); QStringList list = grpSvr.readEntry("cmdline history", QStringList()); cmdLine->setHistoryItems(list); connect(cmdLine, SIGNAL(returnPressed(QString)), this, SLOT(slotRun())); connect(cmdLine, SIGNAL(returnPressed(QString)), cmdLine->lineEdit(), SLOT(clear())); connect(cmdLine, SIGNAL(returnToPanel()), this, SLOT(slotReturnFocus())); cmdLine->setWhatsThis(i18n("

Well, it is actually quite simple: you type your command here and Krusader obeys.

Tip: move within command line history with <Up> and <Down> arrows.

")); layout->addWidget(cmdLine, 0, 1); buttonAddPlaceholder = new QToolButton(this); buttonAddPlaceholder->setAutoRaise(true); buttonAddPlaceholder->setIcon(SmallIcon("list-add")); connect(buttonAddPlaceholder, SIGNAL(clicked()), this, SLOT(addPlaceholder())); buttonAddPlaceholder->setWhatsThis(i18n("Add Placeholders for the selected files in the panel.")); layout->addWidget(buttonAddPlaceholder, 0, 2); // a run in terminal button terminal = new KCMDModeButton(this); terminal->setAutoRaise(true); layout->addWidget(terminal, 0, 3); layout->activate(); } KCMDLine::~KCMDLine() { KConfigGroup grpSvr(krConfig, "Private"); QStringList list = cmdLine->historyItems(); //qWarning() << list[0]; grpSvr.writeEntry("cmdline history", list); krConfig->sync(); } void KCMDLine::addPlaceholder() { AddPlaceholderPopup popup(this); QString exp = popup.getPlaceholder( buttonAddPlaceholder->mapToGlobal(QPoint(0, 0)) ); this->addText(exp); } void KCMDLine::setCurrent(const QString &path) { cmdLine->setPath(path); completion.setDir(QUrl::fromLocalFile(path)); // make sure our command is executed in the right directory // This line is important for Krusader overall functions -> do not remove ! QDir::setCurrent(path); } void KCMDLine::slotRun() { const QString command1(cmdLine->currentText()); if (command1.isEmpty()) return; cmdLine->addToHistory(command1); // bugfix by aardvark: current editline is destroyed by addToHistory() in some cases cmdLine->setEditText(command1); if (command1.simplified().left(3) == "cd ") { // cd command effect the active panel QString dir = command1.right(command1.length() - command1.indexOf(" ")).trimmed(); if (dir == "~") dir = QDir::homePath(); else if (dir.left(1) != "/" && !dir.contains(":/")) dir = cmdLine->path() + (cmdLine->path() == "/" ? "" : "/") + dir; SLOTS->refresh(QUrl::fromUserInput(dir,QDir::currentPath(),QUrl::AssumeLocalFile)); } else { exec(); cmdLine->clearEditText(); } } void KCMDLine::slotReturnFocus() { MAIN_VIEW->cmdLineUnFocus(); } static const KrActionBase::ExecType execModesMenu[] = { KrActionBase::Normal, KrActionBase::CollectOutputSeparateStderr, KrActionBase::CollectOutput, KrActionBase::Terminal, KrActionBase::RunInTE, }; QString KCMDLine::command() const { return cmdLine->currentText(); } KrActionBase::ExecType KCMDLine::execType() const { KConfigGroup grp(krConfig, "Private"); int i = grp.readEntry("Command Execution Mode", (int)0); return execModesMenu[i]; } QString KCMDLine::startpath() const { return cmdLine->path(); // return path->text().left(path->text().length() - 1); } QString KCMDLine::user() const { return QString(); } QString KCMDLine::text() const { return cmdLine->currentText(); } bool KCMDLine::acceptURLs() const { return false; } bool KCMDLine::confirmExecution() const { return false; } bool KCMDLine::doSubstitution() const { return true; } void KCMDLine::setText(QString text) { cmdLine->lineEdit()->setText(text); } diff --git a/krusader/GUI/kcmdline.h b/krusader/GUI/kcmdline.h index 7a7c4e69..38f31359 100644 --- a/krusader/GUI/kcmdline.h +++ b/krusader/GUI/kcmdline.h @@ -1,129 +1,119 @@ -/*************************************************************************** - kcmdline.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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); virtual bool eventFilter(QObject *watched, QEvent *e) Q_DECL_OVERRIDE; QString path() { return _path; } void setPath(QString path); signals: void returnToPanel(); protected slots: void doLayout(); protected: virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; virtual void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; void updateLineEditGeometry(); QLabel *_pathLabel; QString _path; bool _handlingLineEditResize; }; class KCMDLine : public QWidget, KrActionBase { Q_OBJECT public: explicit KCMDLine(QWidget *parent = 0); ~KCMDLine(); void setCurrent(const QString &path); //virtual methods from KrActionBase void setText(QString text); QString command() const; ExecType execType() const; QString startpath() const; QString user() const; QString text() const; bool acceptURLs() const; bool confirmExecution() const; bool doSubstitution() const; signals: void signalRun(); public slots: void slotReturnFocus(); // returns keyboard focus to panel void slotRun(); void addPlaceholder(); void addText(QString text) { cmdLine->lineEdit()->setText(cmdLine->lineEdit()->text() + text); } void popup() { cmdLine->showPopup(); } protected: virtual void focusInEvent(QFocusEvent*) Q_DECL_OVERRIDE { cmdLine->setFocus(); } void calcLabelSize(); private: CmdLineCombo *cmdLine; KCMDModeButton *terminal; QToolButton *buttonAddPlaceholder; KShellCompletion completion; }; #endif diff --git a/krusader/GUI/kfnkeys.cpp b/krusader/GUI/kfnkeys.cpp index e842f95c..ccc4153a 100644 --- a/krusader/GUI/kfnkeys.cpp +++ b/krusader/GUI/kfnkeys.cpp @@ -1,84 +1,75 @@ -/*************************************************************************** - kfnkeys.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kfnkeys.h" // QtWidgets #include #include #include "../defaults.h" #include "../krmainwindow.h" #include "../kractions.h" #include "../Panel/listpanelactions.h" KFnKeys::KFnKeys(QWidget *parent, KrMainWindow *mainWindow) : QWidget(parent), mainWindow(mainWindow), buttonList() { buttonList << setup(mainWindow->listPanelActions()->actRenameF2, i18n("Rename")) << setup(mainWindow->listPanelActions()->actViewFileF3, i18n("View")) << setup(mainWindow->listPanelActions()->actEditFileF4, i18n("Edit")) << setup(mainWindow->listPanelActions()->actCopyF5, i18n("Copy")) << setup(mainWindow->listPanelActions()->actMoveF6, i18n("Move")) << setup(mainWindow->listPanelActions()->actNewFolderF7, i18n("Mkdir")) << setup(mainWindow->listPanelActions()->actDeleteF8, i18n("Delete")) << setup(mainWindow->listPanelActions()->actTerminalF9, i18n("Term")) << setup(mainWindow->krActions()->actF10Quit, i18n("Quit")); updateShortcuts(); QGridLayout *layout = new QGridLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); int pos = 0; for(QPair> entry : buttonList) { layout->addWidget(entry.first, 0, pos++); } layout->activate(); } void KFnKeys::updateShortcuts() { for(ButtonEntry entry : buttonList) { entry.first->setText(entry.second.first->shortcut().toString() + ' ' + entry.second.second); } } KFnKeys::ButtonEntry KFnKeys::setup(QAction *action, const QString &text) { QPushButton *button = new QPushButton(this); button->setMinimumWidth(45); button->setToolTip(action->toolTip()); connect(button, &QPushButton::clicked, action, &QAction::trigger); return QPair>(button, QPair(action, text)); } diff --git a/krusader/GUI/kfnkeys.h b/krusader/GUI/kfnkeys.h index 7f5b7f21..f7dbf440 100644 --- a/krusader/GUI/kfnkeys.h +++ b/krusader/GUI/kfnkeys.h @@ -1,63 +1,53 @@ -/*************************************************************************** - kfnkeys.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KFNKEYS_H #define KFNKEYS_H // QtWidgets #include #include #include #include class KrMainWindow; // Function Keys widget /////////////////////// class KFnKeys : public QWidget { Q_OBJECT public: // constructor KFnKeys(QWidget *parent, KrMainWindow *mainWindow); void updateShortcuts(); private: typedef QPair> ButtonEntry; ButtonEntry setup(QAction *action, const QString &text); KrMainWindow *mainWindow; QList buttonList; }; #endif diff --git a/krusader/GUI/krlistwidget.cpp b/krusader/GUI/krlistwidget.cpp index 9ba25d01..1ae39319 100644 --- a/krusader/GUI/krlistwidget.cpp +++ b/krusader/GUI/krlistwidget.cpp @@ -1,74 +1,64 @@ -/*************************************************************************** - krlistwidget.cpp - ------------------- - copyright : (C) 2008+ by Csaba Karai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2008 Csaba Karai * + * Copyright (C) 2008-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krlistwidget.h" #include "krstyleproxy.h" // QtGui #include KrListWidget::KrListWidget(QWidget * parent) : QListWidget(parent) { KrStyleProxy *style = new KrStyleProxy(); style->setParent(this); setStyle(style); } bool KrListWidget::event(QEvent * event) { switch (event->type()) { // HACK: QT 4 Context menu key isn't handled properly case QEvent::ContextMenu: { QContextMenuEvent* ce = (QContextMenuEvent*) event; if (ce->reason() == QContextMenuEvent::Mouse) { QPoint pos = viewport()->mapFromGlobal(ce->globalPos()); QListWidgetItem * item = itemAt(pos); emit itemRightClicked(item, ce->globalPos()); return true; } else { if (currentItem()) { QRect r = visualItemRect(currentItem()); QPoint p = viewport()->mapToGlobal(QPoint(r.x() + 5, r.y() + 5)); emit itemRightClicked(currentItem(), p); return true; } } } break; default: break; } return QListWidget::event(event); } diff --git a/krusader/GUI/krlistwidget.h b/krusader/GUI/krlistwidget.h index cbe9eb7d..e2420241 100644 --- a/krusader/GUI/krlistwidget.h +++ b/krusader/GUI/krlistwidget.h @@ -1,51 +1,41 @@ -/*************************************************************************** - krlistwidget.h - ------------------- - copyright : (C) 2008+ by Csaba Karai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2008 Csaba Karai * + * Copyright (C) 2008-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRLISTWIDGET_H #define KRLISTWIDGET_H // QtWidgets #include class KrListWidget : public QListWidget { Q_OBJECT public: explicit KrListWidget(QWidget * parent = 0); signals: void itemRightClicked(QListWidgetItem * it, const QPoint & pos); protected: virtual bool event(QEvent * event) Q_DECL_OVERRIDE; }; #endif /* KRLISTVIEW_H */ diff --git a/krusader/GUI/krstyleproxy.cpp b/krusader/GUI/krstyleproxy.cpp index a5af4ba9..dfc5851c 100644 --- a/krusader/GUI/krstyleproxy.cpp +++ b/krusader/GUI/krstyleproxy.cpp @@ -1,87 +1,77 @@ -/*************************************************************************** - krstyleproxy.cpp - ------------------- - copyright : (C) 2008+ by Csaba Karai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2008 Csaba Karai * + * Copyright (C) 2008-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krstyleproxy.h" // QtGui #include #include // QtWidgets #include #include #include "../krglobal.h" void KrStyleProxy::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { if (element == QStyle::PE_FrameFocusRect) { if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(option)) { QColor bg = fropt->backgroundColor; QPen oldPen = painter->pen(); QPen newPen; if (bg.isValid()) { int h, s, v; bg.getHsv(&h, &s, &v); if (v >= 128) newPen.setColor(Qt::black); else newPen.setColor(Qt::white); } else { newPen.setColor(option->palette.foreground().color()); } newPen.setWidth(0); newPen.setStyle(Qt::DotLine); painter->setPen(newPen); QRect focusRect = option->rect /*.adjusted(1, 1, -1, -1) */; painter->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive painter->setPen(oldPen); } } else QProxyStyle::drawPrimitive(element, option, painter, widget); } int KrStyleProxy::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { if (hint == QStyle::SH_ToolTip_WakeUpDelay) { KConfigGroup group(krConfig, "Look&Feel"); const int delay = group.readEntry("Panel Tooltip Delay", 1000); return delay < 0 ? INT_MAX : delay; } // disable instant consecutive tooltips if (hint == QStyle::SH_ToolTip_FallAsleepDelay) { return 0; } return QProxyStyle::styleHint(hint, option, widget, returnData); } diff --git a/krusader/GUI/krstyleproxy.h b/krusader/GUI/krstyleproxy.h index cd7609bc..941436ad 100644 --- a/krusader/GUI/krstyleproxy.h +++ b/krusader/GUI/krstyleproxy.h @@ -1,49 +1,39 @@ -/*************************************************************************** - krstyleproxy.h - ------------------- - copyright : (C) 2008+ by Csaba Karai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2008 Csaba Karai * + * Copyright (C) 2008-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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; int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const Q_DECL_OVERRIDE; }; #endif /* KRSTYLEPROXY_H */ diff --git a/krusader/GUI/krtreewidget.cpp b/krusader/GUI/krtreewidget.cpp index 422a7a41..0357f8cb 100644 --- a/krusader/GUI/krtreewidget.cpp +++ b/krusader/GUI/krtreewidget.cpp @@ -1,212 +1,202 @@ -/*************************************************************************** - krtreewidget.cpp - ------------------- - copyright : (C) 2008+ by Csaba Karai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2008 Csaba Karai * + * Copyright (C) 2008-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krtreewidget.h" #include "krstyleproxy.h" // QtGui #include // QtWidgets #include #include #include #include KrTreeWidget::KrTreeWidget(QWidget * parent) : QTreeWidget(parent), _inResize(false) { setRootIsDecorated(false); setSortingEnabled(true); setAllColumnsShowFocus(true); _stretchingColumn = -1; KrStyleProxy *krstyle = new KrStyleProxy(); krstyle->setParent(this); setStyle(krstyle); } bool KrTreeWidget::event(QEvent * event) { switch (event->type()) { // HACK: QT 4 Context menu key isn't handled properly case QEvent::ContextMenu: { QContextMenuEvent* ce = (QContextMenuEvent*) event; if (ce->reason() == QContextMenuEvent::Mouse) { QPoint pos = viewport()->mapFromGlobal(ce->globalPos()); QTreeWidgetItem * item = itemAt(pos); int column = columnAt(pos.x()); emit itemRightClicked(item, ce->globalPos(), column); return true; } else { if (currentItem()) { QRect r = visualItemRect(currentItem()); QPoint p = viewport()->mapToGlobal(QPoint(r.x() + 5, r.y() + 5)); emit itemRightClicked(currentItem(), p, currentColumn()); return true; } } } break; case QEvent::KeyPress: { // HACK: QT 4 Ctrl+A bug fix: Ctrl+A doesn't work if QTreeWidget contains parent / child items // Insert doesn't change the selections for multi selection modes QKeyEvent* ke = (QKeyEvent*) event; switch (ke->key()) { case Qt::Key_Insert: { if (ke->modifiers() != 0) break; QAbstractItemView::SelectionMode mode = selectionMode(); if (mode != QAbstractItemView::ContiguousSelection && mode != QAbstractItemView::ExtendedSelection && mode != QAbstractItemView::MultiSelection) break; ke->accept(); if (currentItem() == 0) return true; currentItem()->setSelected(!currentItem()->isSelected()); return true; } case Qt::Key_A: if (ke->modifiers() == Qt::ControlModifier) { QAbstractItemView::SelectionMode mode = selectionMode(); if (mode == QAbstractItemView::ContiguousSelection || mode == QAbstractItemView::ExtendedSelection || mode == QAbstractItemView::MultiSelection) { selectAll(); ke->accept(); return true; } } break; default: break; } } break; case QEvent::Resize: { QResizeEvent * re = (QResizeEvent *)event; if (!_inResize && re->oldSize() != re->size()) { if (_stretchingColumn != -1 && columnCount()) { QList< int > columnsSizes; int oldSize = 0; for (int i = 0; i != header()->count(); i++) { columnsSizes.append(header()->sectionSize(i)); oldSize += header()->sectionSize(i); } bool res = QTreeWidget::event(event); int newSize = viewport()->width(); int delta = newSize - oldSize; if (delta) { _inResize = true; for (int i = 0; i != header()->count(); i++) { if (i == _stretchingColumn) { int newNs = columnsSizes[ i ] + delta; if (newNs < 8) newNs = 8; header()->resizeSection(i, newNs); } else if (header()->sectionSize(i) != columnsSizes[ i ]) { header()->resizeSection(i, columnsSizes[ i ]); } } _inResize = false; } return res; } } break; } case QEvent::ToolTip: { QHelpEvent *he = static_cast(event); if (viewport()) { QPoint pos = viewport()->mapFromGlobal(he->globalPos()); QTreeWidgetItem * item = itemAt(pos); int column = columnAt(pos.x()); if (item) { if (!item->toolTip(column).isEmpty()) break; QString tip = item->text(column); int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; int requiredWidth = QFontMetrics(font()).width(tip) + 2 * textMargin; if (column == 0 && indentation()) { int level = 0; QTreeWidgetItem *parent = item; while ((parent = parent->parent())) level++; if (rootIsDecorated()) level++; requiredWidth += level * indentation(); } QIcon icon = item->icon(column); if (!icon.isNull()) { QStyleOptionViewItem opts = viewOptions(); QSize iconSize = icon.actualSize(opts.decorationSize); requiredWidth += iconSize.width(); int pixmapMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, this) + 1; requiredWidth += 2 * pixmapMargin; } if (!tip.isEmpty() && (columnWidth(column) < requiredWidth)) QToolTip::showText(he->globalPos(), tip, this); return true; } } } break; default: break; } return QTreeWidget::event(event); } diff --git a/krusader/GUI/krtreewidget.h b/krusader/GUI/krtreewidget.h index a8bafe3f..e1287293 100644 --- a/krusader/GUI/krtreewidget.h +++ b/krusader/GUI/krtreewidget.h @@ -1,66 +1,56 @@ -/*************************************************************************** - krtreewidget.h - ------------------- - copyright : (C) 2008+ by Csaba Karai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2008 Csaba Karai * + * Copyright (C) 2008-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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: virtual bool event(QEvent * event) Q_DECL_OVERRIDE; private: int _stretchingColumn; bool _inResize; }; #endif /* KRTREEWIDGET_H */ diff --git a/krusader/GUI/krusaderstatus.cpp b/krusader/GUI/krusaderstatus.cpp index 62b19de4..2c466948 100644 --- a/krusader/GUI/krusaderstatus.cpp +++ b/krusader/GUI/krusaderstatus.cpp @@ -1,48 +1,39 @@ -/*************************************************************************** - krusaderstatus.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krusaderstatus.h" // QtGui #include #include KrusaderStatus::KrusaderStatus(QWidget *parent): QStatusBar(parent) { showMessage(i18n("Ready."), 5000); setMaximumHeight(QFontMetrics(font()).height() + 2); } KrusaderStatus::~KrusaderStatus() { } diff --git a/krusader/GUI/krusaderstatus.h b/krusader/GUI/krusaderstatus.h index 866bf059..0e2650f3 100644 --- a/krusader/GUI/krusaderstatus.h +++ b/krusader/GUI/krusaderstatus.h @@ -1,53 +1,43 @@ -/*************************************************************************** - krusaderstatus.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRUSADERSTATUS_H #define KRUSADERSTATUS_H // QtWidgets #include #include #include class KrusaderStatus : public QStatusBar { Q_OBJECT public: explicit KrusaderStatus(QWidget *parent = 0); ~KrusaderStatus(); private: QLabel *mess; }; #endif diff --git a/krusader/GUI/profilemanager.cpp b/krusader/GUI/profilemanager.cpp index 09ce7708..c0877069 100644 --- a/krusader/GUI/profilemanager.cpp +++ b/krusader/GUI/profilemanager.cpp @@ -1,193 +1,183 @@ -/*************************************************************************** - profilemanager.cpp - description - ------------------- - copyright : (C) 2004 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "profilemanager.h" // QtGui #include // QtWidgets #include #include #include #include #include "../krglobal.h" ProfileManager::ProfileManager(QString profileType, QWidget * parent) : QPushButton(parent) { setText(""); setIcon(QIcon::fromTheme("user-identity")); setFixedWidth(16 + 15); setToolTip(i18n("Profiles")); this->profileType = profileType; connect(this, SIGNAL(clicked()), this, SLOT(profilePopup())); KConfigGroup group(krConfig, "Private"); profileList = group.readEntry(profileType, QStringList()); } void ProfileManager::profilePopup() { // profile menu identifiers #define ADD_NEW_ENTRY_ID 1000 #define LOAD_ENTRY_ID 2000 #define REMOVE_ENTRY_ID 3000 #define OVERWRITE_ENTRY_ID 4000 // create the menu QMenu popup, removePopup, overwritePopup; popup.setTitle(i18n("Profiles")); for (int i = 0; i != profileList.count() ; i++) { KConfigGroup group(krConfig, profileType + " - " + profileList[i]); QString name = group.readEntry("Name"); popup.addAction(name)->setData(QVariant((int)(LOAD_ENTRY_ID + i))); removePopup.addAction(name)->setData(QVariant((int)(REMOVE_ENTRY_ID + i))); overwritePopup.addAction(name)->setData(QVariant((int)(OVERWRITE_ENTRY_ID + i))); } popup.addSeparator(); if (profileList.count()) { popup.addMenu(&removePopup)->setText(i18n("Remove entry")); popup.addMenu(&overwritePopup)->setText(i18n("Overwrite entry")); } popup.addAction(i18n("Add new entry"))->setData(QVariant((int)(ADD_NEW_ENTRY_ID))); int result = 0; QAction * res = popup.exec(QCursor::pos()); if (res && res->data().canConvert()) result = res->data().toInt(); // check out the user's selection if (result == ADD_NEW_ENTRY_ID) newProfile(); else if (result >= LOAD_ENTRY_ID && result < LOAD_ENTRY_ID + profileList.count()) { emit loadFromProfile(profileType + " - " + profileList[ result - LOAD_ENTRY_ID ]); } else if (result >= REMOVE_ENTRY_ID && result < REMOVE_ENTRY_ID + profileList.count()) { krConfig->deleteGroup(profileType + " - " + profileList[ result - REMOVE_ENTRY_ID ]); profileList.removeAll(profileList[ result - REMOVE_ENTRY_ID ]); KConfigGroup group(krConfig, "Private"); group.writeEntry(profileType, profileList); krConfig->sync(); } else if (result >= OVERWRITE_ENTRY_ID && result < OVERWRITE_ENTRY_ID + profileList.count()) { emit saveToProfile(profileType + " - " + profileList[ result - OVERWRITE_ENTRY_ID ]); } } void ProfileManager::newProfile(QString defaultName) { QString profile = QInputDialog::getText(this, i18n("Krusader::ProfileManager"), i18n("Enter the profile name:"), QLineEdit::Normal, defaultName); if (!profile.isEmpty()) { int profileNum = 1; while (profileList.contains(QString("%1").arg(profileNum))) profileNum++; QString profileString = QString("%1").arg(profileNum); QString profileName = profileType + " - " + profileString; profileList.append(QString("%1").arg(profileString)); KConfigGroup group(krConfig, "Private"); group.writeEntry(profileType, profileList); KConfigGroup pg(krConfig, profileName); pg.writeEntry("Name", profile); emit saveToProfile(profileName); krConfig->sync(); } } void ProfileManager::deleteProfile(QString name) { for (int i = 0; i != profileList.count() ; i++) { KConfigGroup group(krConfig, profileType + " - " + profileList[ i ]); QString currentName = group.readEntry("Name"); if (name == currentName) { krConfig->deleteGroup(profileType + " - " + profileList[ i ]); profileList.removeAll(profileList[ i ]); KConfigGroup pg(krConfig, "Private"); pg.writeEntry(profileType, profileList); krConfig->sync(); return; } } } void ProfileManager::overwriteProfile(QString name) { for (int i = 0; i != profileList.count() ; i++) { KConfigGroup group(krConfig, profileType + " - " + profileList[ i ]); QString currentName = group.readEntry("Name"); if (name == currentName) { emit saveToProfile(profileType + " - " + profileList[ i ]); return; } } } bool ProfileManager::loadProfile(QString name) { for (int i = 0; i != profileList.count() ; i++) { KConfigGroup group(krConfig, profileType + " - " + profileList[i]); QString currentName = group.readEntry("Name"); if (name == currentName) { emit loadFromProfile(profileType + " - " + profileList[ i ]); return true; } } return false; } QStringList ProfileManager::availableProfiles(QString profileType) { KConfigGroup group(krConfig, "Private"); QStringList profiles = group.readEntry(profileType, QStringList()); QStringList profileNames; for (int i = 0; i != profiles.count() ; i++) { KConfigGroup pg(krConfig, profileType + " - " + profiles[ i ]); profileNames.append(pg.readEntry("Name")); } return profileNames; } diff --git a/krusader/GUI/profilemanager.h b/krusader/GUI/profilemanager.h index a9b94579..b16b76da 100644 --- a/krusader/GUI/profilemanager.h +++ b/krusader/GUI/profilemanager.h @@ -1,87 +1,77 @@ -/*************************************************************************** - profilemanager.h - description - ------------------- - copyright : (C) 2004 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef PROFILEMANAGER_H #define PROFILEMANAGER_H // QtCore #include // QtWidgets #include /** * A generic profile manager: Profiles are arbitray configurations groups and the manager handles * saving/loading multiple groups to/from the configuration. * * A manager instance is responsible for a profile type specified by a type name: * "Panel", "SelectionProfile", "SearcherProfile", "SynchronizerProfile", ... * * Profiles are numbered in the configuration group name and have an additional name property. E.g. * * [Panel - 2] * Name=Media Profile * ... * * This class is view and model at the same time :/ * The GUI button opens a popup menu for selecting, creating, overwriting and removing profiles. */ class ProfileManager : public QPushButton { Q_OBJECT public: explicit ProfileManager(QString profileType, QWidget * parent = 0); /** * @param profileType Type of the profile (sync, search, ...) * @return A list of all available profile-names */ static QStringList availableProfiles(QString profileType); QStringList getNames(); public slots: void profilePopup(); void newProfile(QString defaultName = QString()); void deleteProfile(QString name); void overwriteProfile(QString name); bool loadProfile(QString name); signals: void saveToProfile(QString profileName); void loadFromProfile(QString profileName); private: QString profileType; QStringList profileList; }; #endif /* PROFILEMANAGER_H */ diff --git a/krusader/KViewer/diskusageviewer.cpp b/krusader/KViewer/diskusageviewer.cpp index d51eb287..ec931221 100644 --- a/krusader/KViewer/diskusageviewer.cpp +++ b/krusader/KViewer/diskusageviewer.cpp @@ -1,131 +1,121 @@ -/*************************************************************************** - diskusageviewer.cpp - description - ------------------- - copyright : (C) 2005 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "diskusageviewer.h" // QtWidgets #include #include #include #include "../FileSystem/filesystem.h" #include "../Panel/krpanel.h" #include "../Panel/panelfunc.h" #include "../krglobal.h" DiskUsageViewer::DiskUsageViewer(QWidget *parent) : QWidget(parent), diskUsage(0), statusLabel(0) { layout = new QGridLayout(this); layout->setContentsMargins(0, 0, 0, 0); } DiskUsageViewer::~ DiskUsageViewer() { if (diskUsage) { KConfigGroup group(krConfig, "DiskUsageViewer"); group.writeEntry("View", diskUsage->getActiveView()); delete diskUsage; } } void DiskUsageViewer::openUrl(QUrl url) { if (diskUsage == 0) { diskUsage = new DiskUsage("DiskUsageViewer", this); connect(diskUsage, SIGNAL(enteringDirectory(Directory*)), this, SLOT(slotUpdateStatus())); connect(diskUsage, SIGNAL(status(QString)), this, SLOT(slotUpdateStatus(QString))); connect(diskUsage, SIGNAL(newSearch()), this, SLOT(slotNewSearch())); layout->addWidget(diskUsage, 0, 0); this->show(); diskUsage->show(); KConfigGroup group(krConfig, "DiskUsageViewer"); int view = group.readEntry("View", VIEW_FILELIGHT); if (view < VIEW_LINES || view > VIEW_FILELIGHT) view = VIEW_FILELIGHT; diskUsage->setView(view); } url.setPath(url.adjusted(QUrl::StripTrailingSlash).path()); QUrl baseURL = diskUsage->getBaseURL(); if (!diskUsage->isLoading() && !baseURL.isEmpty()) { if (url.scheme() == baseURL.scheme() && (url.host().isEmpty() || url.host() == baseURL.host())) { QString baseStr = FileSystem::ensureTrailingSlash(baseURL).path(); QString urlStr = FileSystem::ensureTrailingSlash(url).path(); if (urlStr.startsWith(baseStr)) { QString relURL = urlStr.mid(baseStr.length()); if (relURL.endsWith('/')) relURL.truncate(relURL.length() - 1); Directory *dir = diskUsage->getDirectory(relURL); if (dir) { diskUsage->changeDirectory(dir); return; } } } } diskUsage->load(url); } void DiskUsageViewer::closeUrl() { if (diskUsage) diskUsage->close(); } void DiskUsageViewer::setStatusLabel(QLabel *statLabel, QString pref) { statusLabel = statLabel; prefix = pref; } void DiskUsageViewer::slotUpdateStatus(QString status) { if (statusLabel) { if (status.isEmpty()) { Directory * dir = diskUsage->getCurrentDir(); if (dir) status = prefix + dir->name() + " [" + KIO::convertSize(dir->size()) + ']'; } statusLabel->setText(status); } } void DiskUsageViewer::slotNewSearch() { diskUsage->load(ACTIVE_PANEL->virtualPath()); } diff --git a/krusader/KViewer/diskusageviewer.h b/krusader/KViewer/diskusageviewer.h index 9124b1bb..ee2edc24 100644 --- a/krusader/KViewer/diskusageviewer.h +++ b/krusader/KViewer/diskusageviewer.h @@ -1,74 +1,64 @@ -/*************************************************************************** - diskusageviewer.h - description - ------------------- - copyright : (C) 2005 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2005 Csaba Karai * + * Copyright (C) 2005-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef DISKUSAGEVIEWER_H #define DISKUSAGEVIEWER_H #include "../DiskUsage/diskusage.h" // QtCore #include // QtWidgets #include #include #include class DiskUsageViewer : public QWidget { Q_OBJECT public: explicit DiskUsageViewer(QWidget *parent = 0); ~DiskUsageViewer(); void openUrl(QUrl url); void closeUrl(); void setStatusLabel(QLabel *statLabel, QString pref); inline DiskUsage * getWidget() { return diskUsage; } signals: void openUrlRequest(const QUrl &); protected slots: void slotUpdateStatus(QString status = QString()); void slotNewSearch(); protected: DiskUsage *diskUsage; QGridLayout *layout; QLabel *statusLabel; QString prefix; }; #endif /* DISKUSAGEVIEWER_H */ diff --git a/krusader/KViewer/lister.cpp b/krusader/KViewer/lister.cpp index 13cd8072..89b39f9b 100644 --- a/krusader/KViewer/lister.cpp +++ b/krusader/KViewer/lister.cpp @@ -1,2286 +1,2276 @@ -/*************************************************************************** - lister.cpp - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "lister.h" // QtCore #include #include #include #include #include // QtGui #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include // QtPrintSupport #include #include #include #include #include #include #include #include #include #include #include #include "../krglobal.h" #include "../kractions.h" #include "../GUI/krremoteencodingmenu.h" #define SEARCH_CACHE_CHARS 100000 #define SEARCH_MAX_ROW_LEN 4000 #define CONTROL_CHAR 752 #define CACHE_SIZE 1048576 // cache size set to 1MiB ListerTextArea::ListerTextArea(Lister *lister, QWidget *parent) : KTextEdit(parent), _lister(lister) { connect(this, &QTextEdit::cursorPositionChanged, this, &ListerTextArea::slotCursorPositionChanged); _tabWidth = 4; setWordWrapMode(QTextOption::NoWrap); setLineWrapMode(QTextEdit::NoWrap); // zoom shortcuts connect(new QShortcut(QKeySequence("Ctrl++"), this), SIGNAL(activated()), this, SLOT(zoomIn())); connect(new QShortcut(QKeySequence("Ctrl+-"), this), SIGNAL(activated()), this, SLOT(zoomOut())); // start cursor blinking connect(&_blinkTimer, &QTimer::timeout, this, [=] { if (!_cursorBlinkMutex.tryLock()) { return; } setCursorWidth(cursorWidth() == 0 ? 2 : 0); _cursorBlinkMutex.unlock(); }); _blinkTimer.start(500); } void ListerTextArea::reset() { _screenStartPos = 0; _cursorPos = 0; _cursorAnchorPos = -1; _cursorAtFirstColumn = true; calculateText(); } void ListerTextArea::sizeChanged() { if (_cursorAnchorPos > _lister->fileSize()) _cursorAnchorPos = -1; if (_cursorPos > _lister->fileSize()) _cursorPos = _lister->fileSize(); redrawTextArea(true); } void ListerTextArea::resizeEvent(QResizeEvent * event) { KTextEdit::resizeEvent(event); redrawTextArea(); } void ListerTextArea::calculateText(const bool forcedUpdate) { const QRect contentRect = viewport()->contentsRect(); const QFontMetrics fm(font()); const int fontHeight = std::max(fm.height(), 1); // This is quite accurate (although not perfect) way of getting // a single character width along with its surrounding space. const float fontWidth = (fm.width("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW") - fm.width("W")) / 99.0; const int sizeY = contentRect.height() / fontHeight; _pageSize = sizeY; const int textViewportWidth = std::max(contentRect.width() - (int) fontWidth, 0); setTabStopWidth(fontWidth * _tabWidth); const int sizeX = textViewportWidth / fontWidth; _sizeChanged = (_sizeY != sizeY) || (_sizeX != sizeX) || forcedUpdate; _sizeY = sizeY; _sizeX = sizeX; QList rowStarts; QStringList list = readLines(_screenStartPos, _screenEndPos, _sizeY, &rowStarts); if (_sizeChanged) { _averagePageSize = _screenEndPos - _screenStartPos; setUpScrollBar(); } const QStringList listRemn = readLines(_screenEndPos, _screenEndPos, 1); list << listRemn; if (list != _rowContent) { _cursorBlinkMutex.lock(); _blinkTimer.stop(); setCursorWidth(0); setPlainText(list.join("\n")); if (_cursorAnchorPos == -1 || _cursorAnchorPos == _cursorPos) { clearSelection(); _blinkTimer.start(500); } _cursorBlinkMutex.unlock(); _rowContent = list; _rowStarts = rowStarts; if (_rowStarts.size() < _sizeY) { _rowStarts << _screenEndPos; } } } qint64 ListerTextArea::textToFilePositionOnScreen(const int x, const int y, bool &isfirst) { isfirst = (x == 0); if (y >= _rowStarts.count()) { return 0; } const qint64 rowStart = _rowStarts[ y ]; if (x == 0) { return rowStart; } if (_hexMode) { const qint64 pos = rowStart + _lister->hexPositionToIndex(_sizeX, x); if (pos > _lister->fileSize()) { return _lister->fileSize(); } return pos; } // we can't use fromUnicode because of the invalid encoded chars const int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH; QByteArray chunk = _lister->cacheChunk(rowStart, maxBytes); QTextStream stream(&chunk); stream.setCodec(_lister->codec()); stream.read(x); return rowStart + stream.pos(); } void ListerTextArea::fileToTextPositionOnScreen(const qint64 p, const bool isfirst, int &x, int &y) { // check if cursor is outside of visible area if (p < _screenStartPos || p > _screenEndPos || _rowStarts.count() < 1) { x = -1; y = (p > _screenEndPos) ? -2 : -1; return; } // find row y = 0; while (y < _rowStarts.count() && _rowStarts[ y ] <= p) { y++; } y--; if (y < 0) { x = y = -1; return; } const qint64 rowStart = _rowStarts[ y ]; if (_hexMode) { x = _lister->hexIndexToPosition(_sizeX, (int)(p - rowStart)); return; } // find column const int maxBytes = 2 * _sizeX * MAX_CHAR_LENGTH; x = 0; if (rowStart >= p) { if ((rowStart == p) && !isfirst && y > 0) { const qint64 previousRow = _rowStarts[ y - 1 ]; const QByteArray chunk = _lister->cacheChunk(previousRow, maxBytes); QByteArray cachedBuffer = chunk.left(p - previousRow); QTextStream stream(&cachedBuffer); stream.setCodec(_lister->codec()); stream.read(_rowContent[ y - 1].length()); if (previousRow + stream.pos() == p) { y--; x = _rowContent[ y ].length(); } } return; } const QByteArray chunk = _lister->cacheChunk(rowStart, maxBytes); const QByteArray cachedBuffer = chunk.left(p - rowStart); x = _lister->codec()->toUnicode(cachedBuffer).length(); } void ListerTextArea::getCursorPosition(int &x, int &y) { getScreenPosition(textCursor().position(), x, y); } void ListerTextArea::getScreenPosition(const int position, int &x, int &y) { x = position; y = 0; foreach (const QString &row, _rowContent) { const int rowLen = row.length() + 1; if (x < rowLen) { return; } x -= rowLen; y++; } } void ListerTextArea::setCursorPositionOnScreen(const int x, const int y, const int anchorX, const int anchorY) { setCursorWidth(0); int finalX = x; int finalY = y; if (finalX == -1 || finalY < 0) { if (anchorY == -1) { return; } if (finalY == -2) { finalY = _sizeY; finalX = (_rowContent.count() > _sizeY) ? _rowContent[ _sizeY ].length() : 0; } else finalX = finalY = 0; } const int realSizeY = std::min(_sizeY + 1, _rowContent.count()); const auto setUpCursor = [&] (const int cursorX, const int cursorY, const QTextCursor::MoveMode mode) -> bool { if (cursorY > realSizeY) { return false; } _skipCursorChangedListener = true; moveCursor(QTextCursor::Start, mode); for (int i = 0; i < cursorY; i++) { moveCursor(QTextCursor::Down, mode); } int finalCursorX = cursorX; if (_rowContent.count() > cursorY && finalCursorX > _rowContent[ cursorY ].length()) { finalCursorX = _rowContent[ cursorY ].length(); } for (int i = 0; i < finalCursorX; i++) { moveCursor(QTextCursor::Right, mode); } _skipCursorChangedListener = false; return true; }; QTextCursor::MoveMode mode = QTextCursor::MoveAnchor; // set cursor anchor if (anchorX != -1 && anchorY != -1) { const bool canContinue = setUpCursor(anchorX, anchorY, mode); if (!canContinue) { return; } mode = QTextCursor::KeepAnchor; } // set cursor position setUpCursor(finalX, finalY, mode); } qint64 ListerTextArea::getCursorPosition(bool &isfirst) { if (cursorWidth() == 0) { isfirst = _cursorAtFirstColumn; return _cursorPos; } int x, y; getCursorPosition(x, y); return textToFilePositionOnScreen(x, y, isfirst); } void ListerTextArea::setCursorPositionInDocument(const qint64 p, const bool isfirst) { _cursorPos = p; int x, y; fileToTextPositionOnScreen(p, isfirst, x, y); bool startBlinkTimer = _screenStartPos <= _cursorPos && _cursorPos <= _screenEndPos; int anchorX = -1, anchorY = -1; if (_cursorAnchorPos != -1 && _cursorAnchorPos != p) { int anchPos = _cursorAnchorPos; bool anchorBelow = false, anchorAbove = false; if (anchPos < _screenStartPos) { anchPos = _screenStartPos; anchorY = -2; anchorAbove = true; } if (anchPos > _screenEndPos) { anchPos = _screenEndPos; anchorY = -3; anchorBelow = true; } fileToTextPositionOnScreen(anchPos, isfirst, anchorX, anchorY); if (_hexMode) { if (anchorAbove) { anchorX = 0; } if (anchorBelow && _rowContent.count() > 0) { anchorX = _rowContent[ 0 ].length(); } } startBlinkTimer = startBlinkTimer && !anchorAbove && !anchorBelow; } if (startBlinkTimer) { _blinkTimer.start(500); } setCursorPositionOnScreen(x, y, anchorX, anchorY); _lister->slotUpdate(); } void ListerTextArea::slotCursorPositionChanged() { if (_skipCursorChangedListener) { return; } int cursorX, cursorY; getCursorPosition(cursorX, cursorY); _cursorAtFirstColumn = (cursorX == 0); _cursorPos = textToFilePositionOnScreen(cursorX, cursorY, _cursorAtFirstColumn); _lister->slotUpdate(); } QString ListerTextArea::readSection(const qint64 p1, const qint64 p2) { if (p1 == p2) return QString(); qint64 sel1 = p1; qint64 sel2 = p2; if (sel1 > sel2) { std::swap(sel1, sel2); } QString section; if (_hexMode) { while (sel1 != sel2) { const QStringList list = _lister->readHexLines(sel1, sel2, _sizeX, 1); if (list.isEmpty()) { break; } if (!section.isEmpty()) { section += QChar('\n'); } section += list.at(0); } return section; } qint64 pos = sel1; QScopedPointer decoder(_lister->codec()->makeDecoder()); do { const int maxBytes = std::min(_sizeX * _sizeY * MAX_CHAR_LENGTH, (int) (sel2 - pos)); const QByteArray chunk = _lister->cacheChunk(pos, maxBytes); if (chunk.isEmpty()) break; section += decoder->toUnicode(chunk); pos += chunk.size(); } while (pos < sel2); return section; } QStringList ListerTextArea::readLines(qint64 filePos, qint64 &endPos, const int lines, QList * locs) { QStringList list; if (_hexMode) { endPos = _lister->fileSize(); if (filePos >= endPos) { return list; } const int bytes = _lister->hexBytesPerLine(_sizeX); qint64 startPos = (filePos / bytes) * bytes; qint64 shiftPos = startPos; list = _lister->readHexLines(shiftPos, endPos, _sizeX, lines); endPos = shiftPos; if (locs) { for (int i = 0; i < list.count(); i++) { (*locs) << startPos; startPos += bytes; } } return list; } endPos = filePos; const int maxBytes = _sizeX * _sizeY * MAX_CHAR_LENGTH; const QByteArray chunk = _lister->cacheChunk(filePos, maxBytes); if (chunk.isEmpty()) return list; int byteCounter = 0; QString row = ""; int effLength = 0; if (locs) (*locs) << filePos; bool skipImmediateNewline = false; const auto performNewline = [&] (qint64 nextRowStartOffset) { list << row; effLength = 0; row = ""; if (locs) { (*locs) << (filePos + nextRowStartOffset); } }; QScopedPointer decoder(_lister->codec()->makeDecoder()); while (byteCounter < chunk.size() && list.size() < lines) { const int lastCnt = byteCounter; QString chr = decoder->toUnicode(chunk.mid(byteCounter++, 1)); if (chr.isEmpty()) { continue; } if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) { chr = QChar(CONTROL_CHAR); } if (chr == "\n") { if (!skipImmediateNewline) { performNewline(byteCounter); } skipImmediateNewline = false; continue; } skipImmediateNewline = false; if (chr == "\t") { effLength += _tabWidth - (effLength % _tabWidth) - 1; if (effLength > _sizeX) { performNewline(lastCnt); } } row += chr; effLength++; if (effLength >= _sizeX) { performNewline(byteCounter); skipImmediateNewline = true; } } if (list.size() < lines) list << row; endPos = filePos + byteCounter; return list; } void ListerTextArea::setUpScrollBar() { if (_averagePageSize == _lister->fileSize()) { _lister->scrollBar()->setPageStep(0); _lister->scrollBar()->setMaximum(0); _lister->scrollBar()->hide(); _lastPageStartPos = 0; } else { const int maxPage = MAX_CHAR_LENGTH * _sizeX * _sizeY; qint64 pageStartPos = _lister->fileSize() - maxPage; qint64 endPos; if (pageStartPos < 0) pageStartPos = 0; QStringList list = readLines(pageStartPos, endPos, maxPage); if (list.count() <= _sizeY) { _lastPageStartPos = 0; } else { readLines(pageStartPos, _lastPageStartPos, list.count() - _sizeY); } const int maximum = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX : _lastPageStartPos; int pageSize = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _averagePageSize / _lastPageStartPos : _averagePageSize; if (pageSize == 0) pageSize++; _lister->scrollBar()->setPageStep(pageSize); _lister->scrollBar()->setMaximum(maximum); _lister->scrollBar()->show(); } } void ListerTextArea::keyPressEvent(QKeyEvent * ke) { if (KrGlobal::copyShortcut == QKeySequence(ke->key() | ke->modifiers())) { copySelectedToClipboard(); ke->accept(); return; } if (ke->modifiers() == Qt::NoModifier || ke->modifiers() & Qt::ShiftModifier) { qint64 newAnchor = -1; if (ke->modifiers() & Qt::ShiftModifier) { newAnchor = _cursorAnchorPos; if (_cursorAnchorPos == -1) newAnchor = _cursorPos; } switch (ke->key()) { case Qt::Key_F3: ke->accept(); if (ke->modifiers() == Qt::ShiftModifier) _lister->searchPrev(); else _lister->searchNext(); return; case Qt::Key_Home: case Qt::Key_End: _cursorAnchorPos = newAnchor; break; case Qt::Key_Left: { _cursorAnchorPos = newAnchor; ensureVisibleCursor(); int x, y; getCursorPosition(x, y); if (y == 0 && x == 0) slotActionTriggered(QAbstractSlider::SliderSingleStepSub); } break; case Qt::Key_Right: { _cursorAnchorPos = newAnchor; ensureVisibleCursor(); if (textCursor().position() == toPlainText().length()) slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); } break; case Qt::Key_Up: { _cursorAnchorPos = newAnchor; ensureVisibleCursor(); int x, y; getCursorPosition(x, y); if (y == 0) slotActionTriggered(QAbstractSlider::SliderSingleStepSub); } break; case Qt::Key_Down: { _cursorAnchorPos = newAnchor; ensureVisibleCursor(); int x, y; getCursorPosition(x, y); if (y >= _sizeY-1) slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); } break; case Qt::Key_PageDown: { _cursorAnchorPos = newAnchor; ensureVisibleCursor(); ke->accept(); int x, y; getCursorPosition(x, y); slotActionTriggered(QAbstractSlider::SliderPageStepAdd); y += _sizeY - _skippedLines; if (y > _rowContent.count()) { y = _rowContent.count() - 1; if (y > 0) x = _rowContent[ y - 1 ].length(); else x = 0; } _cursorPos = textToFilePositionOnScreen(x, y, _cursorAtFirstColumn); setCursorPositionInDocument(_cursorPos, _cursorAtFirstColumn); } return; case Qt::Key_PageUp: { _cursorAnchorPos = newAnchor; ensureVisibleCursor(); ke->accept(); int x, y; getCursorPosition(x, y); slotActionTriggered(QAbstractSlider::SliderPageStepSub); y -= _sizeY - _skippedLines; if (y < 0) { y = 0; x = 0; } _cursorPos = textToFilePositionOnScreen(x, y, _cursorAtFirstColumn); setCursorPositionInDocument(_cursorPos, _cursorAtFirstColumn); } return; } } if (ke->modifiers() == Qt::ControlModifier) { switch (ke->key()) { case Qt::Key_G: ke->accept(); _lister->jumpToPosition(); return; case Qt::Key_F: ke->accept(); _lister->enableSearch(true); return; case Qt::Key_Home: _cursorAnchorPos = -1; ke->accept(); slotActionTriggered(QAbstractSlider::SliderToMinimum); setCursorPositionInDocument((qint64)0, true); return; case Qt::Key_A: case Qt::Key_End: { _cursorAnchorPos = (ke->key() == Qt::Key_A) ? 0 : -1; ke->accept(); slotActionTriggered(QAbstractSlider::SliderToMaximum); const qint64 endPos = _lister->fileSize(); setCursorPositionInDocument(endPos, false); return; } case Qt::Key_Down: ke->accept(); slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); return; case Qt::Key_Up: ke->accept(); slotActionTriggered(QAbstractSlider::SliderSingleStepSub); return; case Qt::Key_PageDown: ke->accept(); slotActionTriggered(QAbstractSlider::SliderPageStepAdd); return; case Qt::Key_PageUp: ke->accept(); slotActionTriggered(QAbstractSlider::SliderPageStepSub); return; } } const int oldAnchor = textCursor().anchor(); KTextEdit::keyPressEvent(ke); handleAnchorChange(oldAnchor); } void ListerTextArea::mousePressEvent(QMouseEvent * e) { KTextEdit::mousePressEvent(e); // do change anchor only when shift is not pressed if (!(QGuiApplication::keyboardModifiers() & Qt::ShiftModifier)) { performAnchorChange(textCursor().anchor()); } } void ListerTextArea::mouseDoubleClickEvent(QMouseEvent * e) { _cursorAnchorPos = -1; const int oldAnchor = textCursor().anchor(); KTextEdit::mouseDoubleClickEvent(e); handleAnchorChange(oldAnchor); } void ListerTextArea::mouseMoveEvent(QMouseEvent * e) { if (e->pos().y() < 0) { slotActionTriggered(QAbstractSlider::SliderSingleStepSub); } else if (e->pos().y() > height()) { slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); } KTextEdit::mouseMoveEvent(e); } void ListerTextArea::wheelEvent(QWheelEvent * e) { int delta = e->delta(); if (delta) { // zooming if (e->modifiers() & Qt::ControlModifier) { e->accept(); if (delta > 0) { zoomIn(); } else { zoomOut(); } return; } if (delta > 0) { e->accept(); while (delta > 0) { slotActionTriggered(QAbstractSlider::SliderSingleStepSub); slotActionTriggered(QAbstractSlider::SliderSingleStepSub); slotActionTriggered(QAbstractSlider::SliderSingleStepSub); delta -= 120; } } else { e->accept(); while (delta < 0) { slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); slotActionTriggered(QAbstractSlider::SliderSingleStepAdd); delta += 120; } } setCursorPositionInDocument(_cursorPos, false); } } void ListerTextArea::slotActionTriggered(int action) { switch (action) { case QAbstractSlider::SliderSingleStepAdd: { qint64 endPos; readLines(_screenStartPos, endPos, 1); if (endPos <= _lastPageStartPos) { _screenStartPos = endPos; } } break; case QAbstractSlider::SliderSingleStepSub: { if (_screenStartPos == 0) { break; } if (_hexMode) { int bytesPerRow = _lister->hexBytesPerLine(_sizeX); _screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow; _screenStartPos -= bytesPerRow; if (_screenStartPos < 0) { _screenStartPos = 0; } break; } int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH; const QByteArray encodedEnter = _lister->codec()->fromUnicode(QString("\n")); qint64 readPos = _screenStartPos - maxSize; if (readPos < 0) { readPos = 0; } maxSize = _screenStartPos - readPos; const QByteArray chunk = _lister->cacheChunk(readPos, maxSize); int from = chunk.size(); while (from > 0) { from--; from = chunk.lastIndexOf(encodedEnter, from); if (from == -1) { from = 0; break; } const int backRef = std::max(from - 20, 0); const int size = from - backRef + encodedEnter.size(); const QString decoded = _lister->codec()->toUnicode(chunk.mid(backRef, size)); if (decoded.endsWith(QLatin1String("\n"))) { if (from < (chunk.size() - encodedEnter.size())) { from += encodedEnter.size(); break; } } } readPos += from; qint64 previousPos = readPos; while (readPos < _screenStartPos) { previousPos = readPos; readLines(readPos, readPos, 1); } _screenStartPos = previousPos; } break; case QAbstractSlider::SliderPageStepAdd: { _skippedLines = 0; qint64 endPos; for (int i = 0; i < _sizeY; i++) { readLines(_screenStartPos, endPos, 1); if (endPos <= _lastPageStartPos) { _screenStartPos = endPos; _skippedLines++; } else { break; } } } break; case QAbstractSlider::SliderPageStepSub: { _skippedLines = 0; if (_screenStartPos == 0) { break; } if (_hexMode) { const int bytesPerRow = _lister->hexBytesPerLine(_sizeX); _screenStartPos = (_screenStartPos / bytesPerRow) * bytesPerRow; _screenStartPos -= _sizeY * bytesPerRow; if (_screenStartPos < 0) { _screenStartPos = 0; } break; } // text lister mode int maxSize = 2 * _sizeX * _sizeY * MAX_CHAR_LENGTH; const QByteArray encodedEnter = _lister->codec()->fromUnicode(QString("\n")); qint64 readPos = _screenStartPos - maxSize; if (readPos < 0) readPos = 0; maxSize = _screenStartPos - readPos; const QByteArray chunk = _lister->cacheChunk(readPos, maxSize); maxSize = chunk.size(); int sizeY = _sizeY + 1; int origSizeY = sizeY; int from = maxSize; int lastEnter = maxSize; bool readNext = true; while (readNext) { readNext = false; while (from > 0) { from--; from = chunk.lastIndexOf(encodedEnter, from); if (from == -1) { from = 0; break; } const int backRef = std::max(from - 20, 0); const int size = from - backRef + encodedEnter.size(); QString decoded = _lister->codec()->toUnicode(chunk.mid(backRef, size)); if (decoded.endsWith(QLatin1String("\n"))) { if (from < (maxSize - encodedEnter.size())) { int arrayStart = from + encodedEnter.size(); decoded = _lister->codec()->toUnicode(chunk.mid(arrayStart, lastEnter - arrayStart)); sizeY -= ((decoded.length() / (_sizeX + 1)) + 1); if (sizeY < 0) { from = arrayStart; break; } } lastEnter = from; } } qint64 searchPos = readPos + from; QList locs; while (searchPos < _screenStartPos) { locs << searchPos; readLines(searchPos, searchPos, 1); } if (locs.count() >= _sizeY) { _screenStartPos = locs[ locs.count() - _sizeY ]; } else if (from != 0) { origSizeY += locs.count() + 1; sizeY = origSizeY; readNext = true; } else if (readPos == 0) { _screenStartPos = 0; } } } break; case QAbstractSlider::SliderToMinimum: _screenStartPos = 0; break; case QAbstractSlider::SliderToMaximum: _screenStartPos = _lastPageStartPos; break; case QAbstractSlider::SliderMove: { if (_inSliderOp) // self created call? return; qint64 pos = _lister->scrollBar()->sliderPosition(); if (pos == SLIDER_MAX) { _screenStartPos = _lastPageStartPos; break; } else if (pos == 0) { _screenStartPos = 0; break; } if (_lastPageStartPos > SLIDER_MAX) pos = _lastPageStartPos * pos / SLIDER_MAX; if (pos != 0) { if (_hexMode) { const int bytesPerRow = _lister->hexBytesPerLine(_sizeX); pos = (pos / bytesPerRow) * bytesPerRow; } else { const int maxSize = _sizeX * _sizeY * MAX_CHAR_LENGTH; qint64 readPos = pos - maxSize; if (readPos < 0) readPos = 0; qint64 previousPos = readPos; while (readPos <= pos) { previousPos = readPos; readLines(readPos, readPos, 1); } pos = previousPos; } } _screenStartPos = pos; } break; case QAbstractSlider::SliderNoAction: break; }; _inSliderOp = true; const int value = (_lastPageStartPos > SLIDER_MAX) ? SLIDER_MAX * _screenStartPos / _lastPageStartPos : _screenStartPos; _lister->scrollBar()->setSliderPosition(value); _inSliderOp = false; redrawTextArea(); } void ListerTextArea::redrawTextArea(bool forcedUpdate) { if (_redrawing) { return; } _redrawing = true; bool isfirst; const qint64 pos = getCursorPosition(isfirst); calculateText(forcedUpdate); setCursorPositionInDocument(pos, isfirst); _redrawing = false; } void ListerTextArea::ensureVisibleCursor() { if (_screenStartPos <= _cursorPos && _cursorPos <= _screenEndPos) { return; } int delta = _sizeY / 2; if (delta == 0) delta++; qint64 newScreenStart = _cursorPos; while (delta) { const int maxSize = _sizeX * MAX_CHAR_LENGTH; qint64 readPos = newScreenStart - maxSize; if (readPos < 0) readPos = 0; qint64 previousPos = readPos; while (readPos < newScreenStart) { previousPos = readPos; readLines(readPos, readPos, 1); if (readPos == previousPos) break; } newScreenStart = previousPos; delta--; } if (newScreenStart > _lastPageStartPos) { newScreenStart = _lastPageStartPos; } _screenStartPos = newScreenStart; slotActionTriggered(QAbstractSlider::SliderNoAction); } void ListerTextArea::setAnchorAndCursor(qint64 anchor, qint64 cursor) { _cursorPos = cursor; _cursorAnchorPos = anchor; ensureVisibleCursor(); setCursorPositionInDocument(cursor, false); } QString ListerTextArea::getSelectedText() { if (_cursorAnchorPos != -1 && _cursorAnchorPos != _cursorPos) { return readSection(_cursorAnchorPos, _cursorPos); } return QString(); } void ListerTextArea::copySelectedToClipboard() { const QString selection = getSelectedText(); if (!selection.isEmpty()) { QApplication::clipboard()->setText(selection); } } void ListerTextArea::clearSelection() { QTextCursor cursor = textCursor(); cursor.clearSelection(); setTextCursor(cursor); _cursorAnchorPos = -1; } void ListerTextArea::performAnchorChange(int anchor) { int x, y; bool isfirst; getScreenPosition(anchor, x, y); _cursorAnchorPos = textToFilePositionOnScreen(x, y, isfirst); } void ListerTextArea::handleAnchorChange(int oldAnchor) { const int anchor = textCursor().anchor(); if (oldAnchor != anchor) { performAnchorChange(anchor); } } void ListerTextArea::setHexMode(bool hexMode) { bool isfirst; const qint64 pos = getCursorPosition(isfirst); _hexMode = hexMode; _screenStartPos = 0; calculateText(true); setCursorPositionInDocument(pos, isfirst); ensureVisibleCursor(); } void ListerTextArea::zoomIn(int range) { KTextEdit::zoomIn(range); redrawTextArea(); } void ListerTextArea::zoomOut(int range) { KTextEdit::zoomOut(range); redrawTextArea(); } ListerPane::ListerPane(Lister *lister, QWidget *parent) : QWidget(parent), _lister(lister) { } bool ListerPane::event(QEvent *e) { const bool handled = ListerPane::handleCloseEvent(e); if (!handled) { return QWidget::event(e); } return true; } bool ListerPane::handleCloseEvent(QEvent *e) { if (e->type() == QEvent::ShortcutOverride) { QKeyEvent *ke = static_cast(e); if (ke->key() == Qt::Key_Escape) { if (_lister->isSearchEnabled()) { _lister->searchDelete(); _lister->enableSearch(false); ke->accept(); return true; } if (!_lister->textArea()->getSelectedText().isEmpty()) { _lister->textArea()->clearSelection(); ke->accept(); return true; } } } return false; } ListerBrowserExtension::ListerBrowserExtension(Lister * lister) : KParts::BrowserExtension(lister) { _lister = lister; emit enableAction("copy", true); emit enableAction("print", true); } void ListerBrowserExtension::copy() { _lister->textArea()->copySelectedToClipboard(); } void ListerBrowserExtension::print() { _lister->print(); } class ListerEncodingMenu : public KrRemoteEncodingMenu { public: ListerEncodingMenu(Lister *lister, const QString &text, const QString &icon, KActionCollection *parent) : KrRemoteEncodingMenu(text, icon, parent), _lister(lister) { } protected: virtual QString currentCharacterSet() { return _lister->characterSet(); } virtual void chooseDefault() { _lister->setCharacterSet(QString()); } virtual void chooseEncoding(QString encodingName) { QString charset = KCharsets::charsets()->encodingForName(encodingName); _lister->setCharacterSet(charset); } Lister * _lister; }; Lister::Lister(QWidget *parent) : KParts::ReadOnlyPart(parent) { setXMLFile("krusaderlisterui.rc"); _actionSaveSelected = new QAction(QIcon::fromTheme("document-save"), i18n("Save selection..."), this); connect(_actionSaveSelected, SIGNAL(triggered(bool)), SLOT(saveSelected())); actionCollection()->addAction("save_selected", _actionSaveSelected); _actionSaveAs = new QAction(QIcon::fromTheme("document-save-as"), i18n("Save as..."), this); connect(_actionSaveAs, SIGNAL(triggered(bool)), SLOT(saveAs())); actionCollection()->addAction("save_as", _actionSaveAs); _actionPrint = new QAction(QIcon::fromTheme("document-print"), i18n("Print..."), this); connect(_actionPrint, SIGNAL(triggered(bool)), SLOT(print())); actionCollection()->addAction("print", _actionPrint); actionCollection()->setDefaultShortcut(_actionPrint, Qt::CTRL + Qt::Key_P); _actionSearch = new QAction(QIcon::fromTheme("system-search"), i18n("Search"), this); connect(_actionSearch, SIGNAL(triggered(bool)), SLOT(searchAction())); actionCollection()->addAction("search", _actionSearch); actionCollection()->setDefaultShortcut(_actionSearch, Qt::CTRL + Qt::Key_F); _actionSearchNext = new QAction(QIcon::fromTheme("go-down"), i18n("Search next"), this); connect(_actionSearchNext, SIGNAL(triggered(bool)), SLOT(searchNext())); actionCollection()->addAction("search_next", _actionSearchNext); actionCollection()->setDefaultShortcut(_actionSearchNext, Qt::Key_F3); _actionSearchPrev = new QAction(QIcon::fromTheme("go-up"), i18n("Search previous"), this); connect(_actionSearchPrev, SIGNAL(triggered(bool)), SLOT(searchPrev())); actionCollection()->addAction("search_prev", _actionSearchPrev); actionCollection()->setDefaultShortcut(_actionSearchPrev, Qt::SHIFT + Qt::Key_F3); _actionJumpToPosition = new QAction(QIcon::fromTheme("go-jump"), i18n("Jump to position"), this); connect(_actionJumpToPosition, SIGNAL(triggered(bool)), SLOT(jumpToPosition())); actionCollection()->addAction("jump_to_position", _actionJumpToPosition); actionCollection()->setDefaultShortcut(_actionJumpToPosition, Qt::CTRL + Qt::Key_G); _actionHexMode = new QAction(QIcon::fromTheme("document-preview"), i18n("Hex mode"), this); connect(_actionHexMode, SIGNAL(triggered(bool)), SLOT(toggleHexMode())); actionCollection()->addAction("hex_mode", _actionHexMode); actionCollection()->setDefaultShortcut(_actionHexMode, Qt::CTRL + Qt::Key_H); new ListerEncodingMenu(this, i18n("Select charset"), "character-set", actionCollection()); QWidget * widget = new ListerPane(this, parent); widget->setFocusPolicy(Qt::StrongFocus); QGridLayout *grid = new QGridLayout(widget); _textArea = new ListerTextArea(this, widget); _textArea->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); _textArea->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); _textArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); _textArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); widget->setFocusProxy(_textArea); grid->addWidget(_textArea, 0, 0); _scrollBar = new QScrollBar(Qt::Vertical, widget); grid->addWidget(_scrollBar, 0, 1); _scrollBar->hide(); QWidget * statusWidget = new QWidget(widget); QHBoxLayout *hbox = new QHBoxLayout(statusWidget); _listerLabel = new QLabel(i18n("Lister:"), statusWidget); hbox->addWidget(_listerLabel); _searchProgressBar = new QProgressBar(statusWidget); _searchProgressBar->setMinimum(0); _searchProgressBar->setMaximum(1000); _searchProgressBar->setValue(0); _searchProgressBar->hide(); hbox->addWidget(_searchProgressBar); _searchStopButton = new QToolButton(statusWidget); _searchStopButton->setIcon(QIcon::fromTheme("process-stop")); _searchStopButton->setToolTip(i18n("Stop search")); _searchStopButton->hide(); connect(_searchStopButton, SIGNAL(clicked()), this, SLOT(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, SIGNAL(returnPressed()), this, SLOT(searchNext())); connect(_searchLineEdit, SIGNAL(textChanged(QString)), this, SLOT(searchTextChanged())); hbox->addWidget(_searchLineEdit); _searchNextButton = new QPushButton(QIcon::fromTheme("go-down"), i18n("Next"), statusWidget); _searchNextButton->setToolTip(i18n("Jump to next match")); connect(_searchNextButton, SIGNAL(clicked()), this, SLOT(searchNext())); hbox->addWidget(_searchNextButton); _searchPrevButton = new QPushButton(QIcon::fromTheme("go-up"), i18n("Previous"), statusWidget); _searchPrevButton->setToolTip(i18n("Jump to previous match")); connect(_searchPrevButton, SIGNAL(clicked()), this, SLOT(searchPrev())); hbox->addWidget(_searchPrevButton); _searchOptions = new QPushButton(i18n("Options"), statusWidget); _searchOptions->setToolTip(i18n("Modify search behavior")); QMenu * menu = new QMenu(); _fromCursorAction = menu->addAction(i18n("From cursor")); _fromCursorAction->setCheckable(true); _fromCursorAction->setChecked(true); _caseSensitiveAction = menu->addAction(i18n("Case sensitive")); _caseSensitiveAction->setCheckable(true); _matchWholeWordsOnlyAction = menu->addAction(i18n("Match whole words only")); _matchWholeWordsOnlyAction->setCheckable(true); _regExpAction = menu->addAction(i18n("RegExp")); _regExpAction->setCheckable(true); _hexAction = menu->addAction(i18n("Hexadecimal")); _hexAction->setCheckable(true); _searchOptions->setMenu(menu); hbox->addWidget(_searchOptions); hbox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); _statusLabel = new QLabel(statusWidget); hbox->addWidget(_statusLabel); grid->addWidget(statusWidget, 1, 0, 1, 2); setWidget(widget); connect(_scrollBar, SIGNAL(actionTriggered(int)), _textArea, SLOT(slotActionTriggered(int))); connect(&_searchUpdateTimer, &QTimer::timeout, this, &Lister::slotUpdate); new ListerBrowserExtension(this); enableSearch(false); _tempFile = new QTemporaryFile(this); _tempFile->setFileTemplate(QDir::tempPath() + QLatin1String("/krusader_lister.XXXXXX")); } bool Lister::openUrl(const QUrl &listerUrl) { _downloading = false; setUrl(listerUrl); _fileSize = 0; if (listerUrl.isLocalFile()) { _filePath = listerUrl.path(); if (!QFile::exists(_filePath)) return false; _fileSize = getFileSize(); } else { if (_tempFile->isOpen()) { _tempFile->close(); } _tempFile->open(); _filePath = _tempFile->fileName(); KIO::TransferJob *downloadJob = KIO::get(listerUrl, KIO::NoReload, KIO::HideProgressInfo); connect(downloadJob, &KIO::TransferJob::data, this, [=](KIO::Job*, QByteArray array) { if (array.size() != 0) { _tempFile->write(array); } }); connect(downloadJob, &KIO::TransferJob::result, this, [=](KJob *job) { _tempFile->flush(); if (job->error()) { /* any error occurred? */ KIO::TransferJob *kioJob = (KIO::TransferJob *)job; KMessageBox::error(_textArea, i18n("Error reading file %1.", kioJob->url().toDisplayString(QUrl::PreferLocalFile))); } _downloading = false; _downloadUpdateTimer.stop(); slotUpdate(); }); connect(&_downloadUpdateTimer, &QTimer::timeout, this, [&]() { slotUpdate(); }); _downloadUpdateTimer.start(500); _downloading = true; } // invalidate cache _cache.clear(); _textArea->reset(); emit started(0); emit setWindowCaption(listerUrl.toDisplayString()); emit completed(); return true; } QByteArray Lister::cacheChunk(const qint64 filePos, const int maxSize) { if (filePos >= _fileSize) { return QByteArray(); } int size = maxSize; if (_fileSize - filePos < size) { size = _fileSize - filePos; } if (!_cache.isEmpty() && (filePos >= _cachePos) && (filePos + size <= _cachePos + _cache.size())) { return _cache.mid(filePos - _cachePos, size); } const int negativeOffset = CACHE_SIZE * 2 / 5; qint64 cachePos = filePos - negativeOffset; if (cachePos < 0) cachePos = 0; QFile sourceFile(_filePath); if (!sourceFile.open(QIODevice::ReadOnly)) { return QByteArray(); } if (!sourceFile.seek(cachePos)) { return QByteArray(); } const QByteArray bytes = sourceFile.read(CACHE_SIZE); if (bytes.isEmpty()) { return bytes; } _cache = bytes; _cachePos = cachePos; const qint64 cacheRefIndex = filePos - _cachePos; int newSize = bytes.size() - cacheRefIndex; if (newSize < size) size = newSize; return _cache.mid(cacheRefIndex, size); } qint64 Lister::getFileSize() { return QFile(_filePath).size(); } void Lister::guiActivateEvent(KParts::GUIActivateEvent * event) { if (event->activated()) { slotUpdate(); _textArea->redrawTextArea(true); } else { enableSearch(false); } KParts::ReadOnlyPart::guiActivateEvent(event); } void Lister::slotUpdate() { const qint64 oldSize = _fileSize; _fileSize = getFileSize(); if (oldSize != _fileSize) _textArea->sizeChanged(); int cursorX = 0, cursorY = 0; _textArea->getCursorPosition(cursorX, cursorY); bool isfirst = false; const qint64 cursor = _textArea->getCursorPosition(isfirst); const int percent = (_fileSize == 0) ? 0 : (int)((201 * cursor) / _fileSize / 2); const QString status = i18n("Column: %1, Position: %2 (%3, %4%)", cursorX, cursor, _fileSize, percent); _statusLabel->setText(status); if (_searchProgressCounter) _searchProgressCounter--; } bool Lister::isSearchEnabled() { return !_searchLineEdit->isHidden() || !_searchProgressBar->isHidden(); } void Lister::enableSearch(const bool enable) { if (enable) { _listerLabel->setText(i18n("Search:")); _searchLineEdit->show(); _searchNextButton->show(); _searchPrevButton->show(); _searchOptions->show(); if (!_searchLineEdit->hasFocus()) { _searchLineEdit->setFocus(); const QString selection = _textArea->getSelectedText(); if (!selection.isEmpty()) { _searchLineEdit->setText(selection); } _searchLineEdit->selectAll(); } } else { _listerLabel->setText(i18n("Lister:")); _searchLineEdit->hide(); _searchNextButton->hide(); _searchPrevButton->hide(); _searchOptions->hide(); _textArea->setFocus(); } } void Lister::searchNext() { search(true); } void Lister::searchPrev() { search(false); } void Lister::search(const bool forward, const bool restart) { _restartFromBeginning = restart; if (_searchInProgress || _searchLineEdit->text().isEmpty()) return; if (_searchLineEdit->isHidden()) enableSearch(true); _searchPosition = forward ? 0 : _fileSize; if (_fromCursorAction->isChecked()) { bool isfirst; qint64 cursor = _textArea->getCursorPosition(isfirst); if (cursor != 0 && !forward) cursor--; if (_searchLastFailedPosition == -1 || _searchLastFailedPosition != cursor) _searchPosition = cursor; } const bool caseSensitive = _caseSensitiveAction->isChecked(); const bool matchWholeWord = _matchWholeWordsOnlyAction->isChecked(); const bool regExp = _regExpAction->isChecked(); const bool hex = _hexAction->isChecked(); if (hex) { QString hexcontent = _searchLineEdit->text(); hexcontent.remove(QLatin1String("0x")); hexcontent.remove(' '); hexcontent.remove('\t'); hexcontent.remove('\n'); hexcontent.remove('\r'); _searchHexQuery = QByteArray(); if (hexcontent.length() & 1) { setColor(false, false); return; } while (!hexcontent.isEmpty()) { const QString hexData = hexcontent.left(2); hexcontent = hexcontent.mid(2); bool ok = true; const int c = hexData.toUInt(&ok, 16); if (!ok) { setColor(false, false); return; } _searchHexQuery.push_back((char) c); } } else { _searchQuery.setContent(_searchLineEdit->text(), caseSensitive, matchWholeWord, codec()->name(), regExp); } _searchIsForward = forward; _searchHexadecimal = hex; QTimer::singleShot(0, this, SLOT(slotSearchMore())); _searchInProgress = true; _searchProgressCounter = 3; enableActions(false); } void Lister::enableActions(const bool state) { _actionSearch->setEnabled(state); _actionSearchNext->setEnabled(state); _actionSearchPrev->setEnabled(state); _actionJumpToPosition->setEnabled(state); if (state) { _searchUpdateTimer.stop(); } else { slotUpdate(); } } void Lister::slotSearchMore() { if (!_searchInProgress) return; if (!_searchUpdateTimer.isActive()) { _searchUpdateTimer.start(200); } updateProgressBar(); if (!_searchIsForward) _searchPosition--; if (_searchPosition < 0 || _searchPosition >= _fileSize) { if (_restartFromBeginning) resetSearchPosition(); else { searchFailed(); return; } } int maxCacheSize = SEARCH_CACHE_CHARS; qint64 searchPos = _searchPosition; bool setPosition = true; if (!_searchIsForward) { qint64 origSearchPos = _searchPosition; searchPos -= maxCacheSize; if (searchPos <= 0) { searchPos = 0; _searchPosition = 0; setPosition = false; } qint64 diff = origSearchPos - searchPos; if (diff < maxCacheSize) maxCacheSize = diff; } const QByteArray chunk = cacheChunk(searchPos, maxCacheSize); if (chunk.isEmpty()) { searchFailed(); return; } const int chunkSize = chunk.size(); qint64 foundAnchor = -1; qint64 foundCursor = -1; int byteCounter = 0; if (_searchHexadecimal) { const int ndx = _searchIsForward ? chunk.indexOf(_searchHexQuery) : chunk.lastIndexOf(_searchHexQuery); if (chunkSize > _searchHexQuery.length()) { if (_searchIsForward) { _searchPosition = searchPos + chunkSize; if ((_searchPosition < _fileSize) && (chunkSize > _searchHexQuery.length())) _searchPosition -= _searchHexQuery.length(); byteCounter = _searchPosition - searchPos; } else { if (_searchPosition > 0) _searchPosition += _searchHexQuery.length(); } } if (ndx != -1) { foundAnchor = searchPos + ndx; foundCursor = foundAnchor + _searchHexQuery.length(); } } else { int rowStart = 0; QString row = ""; QScopedPointer decoder(_codec->makeDecoder()); while (byteCounter < chunkSize) { const QString chr = decoder->toUnicode(chunk.mid(byteCounter++, 1)); if (chr.isEmpty() && byteCounter < chunkSize) { continue; } if (chr != "\n") row += chr; if (chr == "\n" || row.length() >= SEARCH_MAX_ROW_LEN || byteCounter >= chunkSize) { if (setPosition) { _searchPosition = searchPos + byteCounter; if (!_searchIsForward) { _searchPosition++; setPosition = false; } } if (_searchQuery.checkLine(row, !_searchIsForward)) { QByteArray cachedBuffer = chunk.mid(rowStart, chunkSize - rowStart); QTextStream stream(&cachedBuffer); stream.setCodec(_codec); stream.read(_searchQuery.matchIndex()); foundAnchor = searchPos + rowStart + stream.pos(); stream.read(_searchQuery.matchLength()); foundCursor = searchPos + rowStart + stream.pos(); if (_searchIsForward) break; } row = ""; rowStart = byteCounter; } } } if (foundAnchor != -1 && foundCursor != -1) { _textArea->setAnchorAndCursor(foundAnchor, foundCursor); searchSucceeded(); return; } if (_searchIsForward && searchPos + byteCounter >= _fileSize) { if (_restartFromBeginning) resetSearchPosition(); else { searchFailed(); return; } } else if (_searchPosition <= 0 || _searchPosition >= _fileSize) { if (_restartFromBeginning) resetSearchPosition(); else { searchFailed(); return; } } QTimer::singleShot(0, this, SLOT(slotSearchMore())); } void Lister::resetSearchPosition() { _restartFromBeginning = false; _searchPosition = _searchIsForward ? 0 : _fileSize - 1; } void Lister::searchSucceeded() { _searchInProgress = false; setColor(true, false); hideProgressBar(); _searchLastFailedPosition = -1; enableActions(true); } void Lister::searchFailed() { _searchInProgress = false; setColor(false, false); hideProgressBar(); bool isfirst; _searchLastFailedPosition = _textArea->getCursorPosition(isfirst); if (!_searchIsForward) _searchLastFailedPosition--; enableActions(true); } void Lister::searchDelete() { _searchInProgress = false; setColor(false, true); hideProgressBar(); _searchLastFailedPosition = -1; enableActions(true); } void Lister::searchTextChanged() { searchDelete(); if (_fileSize < 0x10000) { // autosearch files less than 64k if (!_searchLineEdit->text().isEmpty()) { bool isfirst; const qint64 anchor = _textArea->getCursorAnchor(); const qint64 cursor = _textArea->getCursorPosition(isfirst); if (cursor > anchor && anchor != -1) { _textArea->setCursorPositionInDocument(anchor, true); } search(true, true); } } } void Lister::setColor(const bool match, const bool restore) { QColor fore, back; if (!restore) { const KConfigGroup gc(krConfig, "Colors"); QString foreground, background; const QPalette p = QGuiApplication::palette(); if (match) { foreground = "Quicksearch Match Foreground"; background = "Quicksearch Match Background"; fore = Qt::black; back = QColor(192, 255, 192); } else { foreground = "Quicksearch Non-match Foreground"; background = "Quicksearch Non-match Background"; fore = Qt::black; back = QColor(255, 192, 192); } if (gc.readEntry(foreground, QString()) == "KDE default") fore = p.color(QPalette::Active, QPalette::Text); else if (!gc.readEntry(foreground, QString()).isEmpty()) fore = gc.readEntry(foreground, fore); if (gc.readEntry(background, QString()) == "KDE default") back = p.color(QPalette::Active, QPalette::Base); else if (!gc.readEntry(background, QString()).isEmpty()) back = gc.readEntry(background, back); } else { back = _originalBackground; fore = _originalForeground; } QPalette pal = _searchLineEdit->palette(); pal.setColor(QPalette::Base, back); pal.setColor(QPalette::Text, fore); _searchLineEdit->setPalette(pal); } void Lister::hideProgressBar() { if (!_searchProgressBar->isHidden()) { _searchProgressBar->hide(); _searchStopButton->hide(); _searchLineEdit->show(); _searchNextButton->show(); _searchPrevButton->show(); _searchOptions->show(); _listerLabel->setText(i18n("Search:")); } } void Lister::updateProgressBar() { if (_searchProgressCounter) return; if (_searchProgressBar->isHidden()) { _searchProgressBar->show(); _searchStopButton->show(); _searchOptions->hide(); _searchLineEdit->hide(); _searchNextButton->hide(); _searchPrevButton->hide(); _listerLabel->setText(i18n("Search position:")); // otherwise focus is set to document tab _textArea->setFocus(); } const qint64 pcnt = (_fileSize == 0) ? 1000 : (2001 * _searchPosition) / _fileSize / 2; const int pctInt = (int) pcnt; if (_searchProgressBar->value() != pctInt) _searchProgressBar->setValue(pctInt); } void Lister::jumpToPosition() { bool ok = true; QString res = QInputDialog::getText(_textArea, i18n("Jump to position"), i18n("Text position:"), QLineEdit::Normal, "0", &ok); if (!ok) return; res = res.trimmed(); qint64 pos = -1; if (res.startsWith(QLatin1String("0x"))) { res = res.mid(2); bool ok; const qulonglong upos = res.toULongLong(&ok, 16); if (!ok) { KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position")); return; } pos = (qint64)upos; } else { bool ok; const qulonglong upos = res.toULongLong(&ok); if (!ok) { KMessageBox::error(_textArea, i18n("Invalid number."), i18n("Jump to position")); return; } pos = (qint64)upos; } if (pos < 0 || pos > _fileSize) { KMessageBox::error(_textArea, i18n("Number out of range."), i18n("Jump to position")); return; } _textArea->deleteAnchor(); _textArea->setCursorPositionInDocument(pos, true); _textArea->ensureVisibleCursor(); } void Lister::saveAs() { const QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister")); if (url.isEmpty()) return; QUrl sourceUrl; if (!_downloading) sourceUrl = QUrl::fromLocalFile(_filePath); else sourceUrl = this->url(); QList urlList; urlList << sourceUrl; KIO::Job *job = KIO::copy(urlList, url); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); } void Lister::saveSelected() { bool isfirst; const qint64 start = _textArea->getCursorAnchor(); const qint64 end = _textArea->getCursorPosition(isfirst); if (start == -1 || start == end) { KMessageBox::error(_textArea, i18n("Nothing is selected."), i18n("Save selection...")); return; } if (start > end) { _savePosition = end; _saveEnd = start; } else { _savePosition = start; _saveEnd = end; } const QUrl url = QFileDialog::getSaveFileUrl(_textArea, i18n("Lister")); if (url.isEmpty()) return; KIO::Job *saveJob = KIO::put(url, -1, KIO::Overwrite); connect(saveJob, SIGNAL(dataReq(KIO::Job*,QByteArray&)), this, SLOT(slotDataSend(KIO::Job*,QByteArray&))); connect(saveJob, SIGNAL(result(KJob*)), this, SLOT(slotSendFinished(KJob*))); saveJob->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(saveJob); saveJob->uiDelegate()->setAutoErrorHandlingEnabled(true); _actionSaveSelected->setEnabled(false); } void Lister::slotDataSend(KIO::Job *, QByteArray &array) { if (_savePosition >= _saveEnd) { array = QByteArray(); return; } qint64 max = _saveEnd - _savePosition; if (max > 1000) max = 1000; array = cacheChunk(_savePosition, (int) max); _savePosition += array.size(); } void Lister::slotSendFinished(KJob *) { _actionSaveSelected->setEnabled(true); } void Lister::setCharacterSet(const QString set) { _characterSet = set; if (_characterSet.isEmpty()) { _codec = QTextCodec::codecForLocale(); } else { _codec = KCharsets::charsets()->codecForName(_characterSet); } _textArea->redrawTextArea(true); } void Lister::print() { bool isfirst; const qint64 anchor = _textArea->getCursorAnchor(); const qint64 cursor = _textArea->getCursorPosition(isfirst); const bool hasSelection = (anchor != -1 && anchor != cursor); const QString docName = url().fileName(); QPrinter printer; printer.setDocName(docName); QScopedPointer printDialog(new QPrintDialog(&printer, _textArea)); if (hasSelection) { printDialog->addEnabledOption(QAbstractPrintDialog::PrintSelection); } if (!printDialog->exec()) { return; } if (printer.pageOrder() == QPrinter::LastPageFirst) { switch (KMessageBox::warningContinueCancel(_textArea, i18n("Reverse printing is not supported. Continue with normal printing?"))) { case KMessageBox::Continue : break; default: return; } } QPainter painter; painter.begin(&printer); const QString dateString = QDate::currentDate().toString(Qt::SystemLocaleShortDate); const QRect pageRect = printer.pageRect(); const QRect drawingRect(0, 0, pageRect.width(), pageRect.height()); const QFont normalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); const QFontMetrics fmNormal(normalFont); const int normalFontHeight = fmNormal.height(); const QFontMetrics fmFixed(fixedFont); const int fixedFontHeight = std::max(fmFixed.height(), 1); const int fixedFontWidth = std::max(fmFixed.width("W"), 1); const int effPageSize = drawingRect.height() - normalFontHeight - 1; const int rowsPerPage = std::max(effPageSize / fixedFontHeight, 1); const int columnsPerPage = std::max(drawingRect.width() / fixedFontWidth, 1); bool firstPage = true; qint64 startPos = 0; qint64 endPos = _fileSize; if (printer.printRange() == QPrinter::Selection) { if (anchor > cursor) startPos = cursor, endPos = anchor; else startPos = anchor, endPos = cursor; } int page = 0; while (startPos < endPos) { page++; QStringList rows = readLines(startPos, endPos, columnsPerPage, rowsPerPage); // print since set-up fromPage number if (printer.fromPage() && page < printer.fromPage()) { continue; } // print until set-up toPage number if (printer.toPage() && printer.toPage() >= printer.fromPage() && page > printer.toPage()) break; if (!firstPage) { printer.newPage(); } firstPage = false; // Use the painter to draw on the page. painter.setFont(normalFont); painter.drawText(drawingRect, Qt::AlignLeft, dateString); painter.drawText(drawingRect, Qt::AlignHCenter, docName); painter.drawText(drawingRect, Qt::AlignRight, QString("%1").arg(page)); painter.drawLine(0, normalFontHeight, drawingRect.width(), normalFontHeight); painter.setFont(fixedFont); int yOffset = normalFontHeight + 1; foreach (const QString &row, rows) { painter.drawText(0, yOffset + fixedFontHeight, row); yOffset += fixedFontHeight; } } } QStringList Lister::readLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines) { if (_textArea->hexMode()) { return readHexLines(filePos, endPos, columns, lines); } QStringList list; const int maxBytes = std::min(columns * lines * MAX_CHAR_LENGTH, (int) (endPos - filePos)); if (maxBytes <= 0) { return list; } const QByteArray chunk = cacheChunk(filePos, maxBytes); if (chunk.isEmpty()) { return list; } QScopedPointer decoder(_codec->makeDecoder()); int byteCounter = 0; QString row = ""; bool skipImmediateNewline = false; while (byteCounter < chunk.size() && list.size() < lines) { QString chr = decoder->toUnicode(chunk.mid(byteCounter++, 1)); if (chr.isEmpty()) { continue; } // replace unreadable characters if ((chr[ 0 ] < 32) && (chr[ 0 ] != '\n') && (chr[ 0 ] != '\t')) { chr = QChar(' '); } // handle newline if (chr == "\n") { if (!skipImmediateNewline) { list << row; row = ""; } skipImmediateNewline = false; continue; } skipImmediateNewline = false; // handle tab if (chr == "\t") { const int tabLength = _textArea->tabWidth() - (row.length() % _textArea->tabWidth()); if (row.length() + tabLength > columns) { list << row; row = ""; } row += QString(tabLength, QChar(' ')); } else { // normal printable character row += chr; } if (row.length() >= columns) { list << row; row = ""; skipImmediateNewline = true; } } if (list.size() < lines) { list << row; } filePos += byteCounter; return list; } int Lister::hexPositionDigits() { int positionDigits = 0; qint64 checker = _fileSize; while (checker) { positionDigits++; checker /= 16; } if (positionDigits < 8) { return 8; } return positionDigits; } int Lister::hexBytesPerLine(const int columns) { const int positionDigits = hexPositionDigits(); if (columns >= positionDigits + 5 + 128) { return 32; } if (columns >= positionDigits + 5 + 64) { return 16; } return 8; } QStringList Lister::readHexLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines) { const int positionDigits = hexPositionDigits(); const int bytesPerRow = hexBytesPerLine(columns); QStringList list; const qint64 choppedPos = (filePos / bytesPerRow) * bytesPerRow; const int maxBytes = std::min(bytesPerRow * lines, (int) (endPos - choppedPos)); if (maxBytes <= 0) return list; const QByteArray chunk = cacheChunk(choppedPos, maxBytes); if (chunk.isEmpty()) return list; int cnt = 0; for (int l = 0; l < lines; l++) { if (filePos >= endPos) { break; } const qint64 printPos = (filePos / bytesPerRow) * bytesPerRow; QString pos; pos.setNum(printPos, 16); while (pos.length() < positionDigits) pos = QString("0") + pos; pos = QString("0x") + pos; pos += QString(": "); QString charData; for (int i = 0; i != bytesPerRow; ++i, ++cnt) { const qint64 currentPos = printPos + i; if (currentPos < filePos || currentPos >= endPos) { pos += QString(" "); charData += QString(" "); } else { char c = chunk.at(cnt); int charCode = (int)c; if (charCode < 0) charCode += 256; QString hex; hex.setNum(charCode, 16); if (hex.length() < 2) hex = QString("0") + hex; pos += hex + QString(" "); if (c < 32) c = '.'; charData += QChar(c); } } pos += QString(" ") + charData; list << pos; filePos = printPos + bytesPerRow; } if (filePos > endPos) { filePos = endPos; } return list; } int Lister::hexIndexToPosition(const int columns, const int index) { const int positionDigits = hexPositionDigits(); const int bytesPerRow = hexBytesPerLine(columns); const int finalIndex = std::min(index, bytesPerRow); return positionDigits + 4 + (3*finalIndex); } int Lister::hexPositionToIndex(const int columns, const int position) { const int positionDigits = hexPositionDigits(); const int bytesPerRow = hexBytesPerLine(columns); int finalPosition = position; finalPosition -= 4 + positionDigits; if (finalPosition <= 0) return 0; finalPosition /= 3; if (finalPosition >= bytesPerRow) return bytesPerRow; return finalPosition; } void Lister::toggleHexMode() { setHexMode(!_textArea->hexMode()); } void Lister::setHexMode(const bool mode) { if (mode) { _textArea->setHexMode(true); _actionHexMode->setText(i18n("Text mode")); } else { _textArea->setHexMode(false); _actionHexMode->setText(i18n("Hex mode")); } } diff --git a/krusader/KViewer/lister.h b/krusader/KViewer/lister.h index ac4e9a10..f0564bc9 100644 --- a/krusader/KViewer/lister.h +++ b/krusader/KViewer/lister.h @@ -1,328 +1,318 @@ -/*************************************************************************** - lister.h - description - ------------------- - copyright : (C) 2009 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Csaba Karai * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef LISTER_H #define LISTER_H // QtCore #include #include #include #include // QtGui #include // QtWidgets #include #include #include #include #include #include #include "../FileSystem/krquery.h" #define SLIDER_MAX 10000 #define MAX_CHAR_LENGTH 4 class Lister; class QLabel; class QProgressBar; class QPushButton; class QToolButton; class QAction; class QTemporaryFile; class ListerEncodingMenu; class ListerTextArea : public KTextEdit { Q_OBJECT public: ListerTextArea(Lister *lister, QWidget *parent); void reset(); void calculateText(const bool forcedUpdate = false); void redrawTextArea(const bool forcedUpdate = false); qint64 textToFilePositionOnScreen(const int x, const int y, bool &isfirst); void fileToTextPositionOnScreen(const qint64 p, const bool isfirst, int &x, int &y); int tabWidth() { return _tabWidth; } bool hexMode() { return _hexMode; } void setHexMode(const bool hexMode); void copySelectedToClipboard(); QString getSelectedText(); void clearSelection(); void getCursorPosition(int &x, int &y); qint64 getCursorPosition(bool &isfirst); qint64 getCursorAnchor() { return _cursorAnchorPos; } void setCursorPositionInDocument(const qint64 p, const bool isfirst); void ensureVisibleCursor(); void deleteAnchor() { _cursorAnchorPos = -1; } void setAnchorAndCursor(const qint64 anchor, const qint64 cursor); void sizeChanged(); protected: virtual void resizeEvent(QResizeEvent * event) Q_DECL_OVERRIDE; virtual void keyPressEvent(QKeyEvent * e) Q_DECL_OVERRIDE; virtual void mousePressEvent(QMouseEvent * e) Q_DECL_OVERRIDE; virtual void mouseDoubleClickEvent(QMouseEvent * e) Q_DECL_OVERRIDE; virtual void mouseMoveEvent(QMouseEvent * e) Q_DECL_OVERRIDE; virtual void wheelEvent(QWheelEvent * event) Q_DECL_OVERRIDE; QStringList readLines(const qint64 filePos, qint64 &endPos, const int lines, QList * locs = 0); QString readSection(qint64 p1, qint64 p2); void setUpScrollBar(); void setCursorPositionOnScreen(const int x, const int y, const int anchorX = -1, const int anchorY = -1); void handleAnchorChange(const int oldAnchor); void performAnchorChange(const int anchor); void getScreenPosition(const int position, int &x, int &y); protected slots: void slotActionTriggered(const int action); void slotCursorPositionChanged(); void zoomIn(const int range = 1); void zoomOut(const int range = 1); protected: Lister *_lister; qint64 _screenStartPos = 0; qint64 _screenEndPos = 0; qint64 _averagePageSize = 0; qint64 _lastPageStartPos = 0; int _sizeX = -1; int _sizeY = -1; int _pageSize = 0; int _tabWidth = 4; bool _sizeChanged = false; QStringList _rowContent; QList _rowStarts; qint64 _cursorPos = -1; bool _cursorAtFirstColumn = true; bool _skipCursorChangedListener = false; qint64 _cursorAnchorPos = -1; int _skippedLines = 0; bool _inSliderOp = false; bool _hexMode = false; bool _redrawing = false; QMutex _cursorBlinkMutex; QTimer _blinkTimer; }; class ListerBrowserExtension : public KParts::BrowserExtension { Q_OBJECT public: explicit ListerBrowserExtension(Lister * lister); public slots: void copy(); void print(); protected: Lister *_lister; }; class ListerPane : public QWidget { Q_OBJECT public: ListerPane(Lister *lister, QWidget *parent); protected: virtual bool event(QEvent *event) Q_DECL_OVERRIDE; protected: bool handleCloseEvent(QEvent *e); Lister *_lister; }; class Lister : public KParts::ReadOnlyPart { Q_OBJECT public: explicit Lister(QWidget *parent); QScrollBar *scrollBar() { return _scrollBar; } ListerTextArea *textArea() { return _textArea; } inline qint64 fileSize() { return _fileSize; } QByteArray cacheChunk(const qint64 filePos, const int maxSize); bool isSearchEnabled(); void enableSearch(const bool); void enableActions(const bool); QString characterSet() { return _characterSet; } QTextCodec *codec() { return _codec; } void setCharacterSet(const QString set); void setHexMode(const bool); QStringList readHexLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines); int hexBytesPerLine(const int columns); int hexPositionDigits(); int hexIndexToPosition(const int columns, const int index); int hexPositionToIndex(const int columns, const int position); public slots: void searchAction() { enableSearch(true); } void searchNext(); void searchPrev(); void searchDelete(); void jumpToPosition(); void saveAs(); void saveSelected(); void print(); void toggleHexMode(); void slotUpdate(); protected slots: void slotSearchMore(); void searchSucceeded(); void searchFailed(); void searchTextChanged(); void slotDataSend(KIO::Job *, QByteArray &); void slotSendFinished(KJob *); protected: virtual bool openUrl(const QUrl &url) Q_DECL_OVERRIDE; virtual bool closeUrl() Q_DECL_OVERRIDE { return true; } virtual bool openFile() Q_DECL_OVERRIDE { return true; } virtual void guiActivateEvent(KParts::GUIActivateEvent * event) Q_DECL_OVERRIDE; void setColor(const bool match, const bool restore); void hideProgressBar(); void updateProgressBar(); void resetSearchPosition(); qint64 getFileSize(); void search(const bool forward, const bool restart = false); QStringList readLines(qint64 &filePos, const qint64 endPos, const int columns, const int lines); QTimer _searchUpdateTimer; ListerTextArea *_textArea; QScrollBar *_scrollBar; QLabel *_listerLabel; KLineEdit *_searchLineEdit; QProgressBar *_searchProgressBar; QToolButton *_searchStopButton; QPushButton *_searchNextButton; QPushButton *_searchPrevButton; bool _searchInProgress = false; bool _searchHexadecimal = false; QPushButton *_searchOptions; QLabel *_statusLabel; QAction *_fromCursorAction; QAction *_caseSensitiveAction; QAction *_matchWholeWordsOnlyAction; QAction *_regExpAction; QAction *_hexAction; QAction *_actionSaveSelected; QAction *_actionSaveAs; QAction *_actionPrint; QAction *_actionSearch; QAction *_actionSearchNext; QAction *_actionSearchPrev; QAction *_actionJumpToPosition; QAction *_actionHexMode; QString _filePath; qint64 _fileSize = 0; QByteArray _cache; qint64 _cachePos = 0; KRQuery _searchQuery; QByteArray _searchHexQuery; qint64 _searchPosition = 0; bool _searchIsForward = true; qint64 _searchLastFailedPosition = -1; int _searchProgressCounter = 0; QColor _originalBackground; QColor _originalForeground; QString _characterSet; QTextCodec *_codec = QTextCodec::codecForLocale(); QTemporaryFile *_tempFile = 0; bool _downloading = false; bool _restartFromBeginning = false; QTimer _downloadUpdateTimer; qint64 _savePosition = 0; qint64 _saveEnd = 0; }; #endif // __LISTER_H__ diff --git a/krusader/Konfigurator/kgadvanced.cpp b/krusader/Konfigurator/kgadvanced.cpp index 27861238..784a7484 100644 --- a/krusader/Konfigurator/kgadvanced.cpp +++ b/krusader/Konfigurator/kgadvanced.cpp @@ -1,124 +1,114 @@ -/*************************************************************************** - kgadvanced.cpp - description - ------------------- - copyright : (C) 2004 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kgadvanced.h" #include "../defaults.h" // QtWidgets #include #include #include #include KgAdvanced::KgAdvanced(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { QWidget *innerWidget = new QFrame(this); setWidget(innerWidget); setWidgetResizable(true); QGridLayout *kgAdvancedLayout = new QGridLayout(innerWidget); kgAdvancedLayout->setSpacing(6); // -------------------------- GENERAL GROUPBOX ---------------------------------- QGroupBox *generalGrp = createFrame(i18n("General"), innerWidget); QGridLayout *generalGrid = createGridLayout(generalGrp); KONFIGURATOR_CHECKBOX_PARAM generalSettings[] = // cfg_class cfg_name default text restart tooltip { {"Advanced", "AutoMount", _AutoMount, i18n("Automount filesystems"), false, i18n("When stepping into a folder which is defined as a mount point in the fstab, try mounting it with the defined parameters.")} }; KonfiguratorCheckBoxGroup *generals = createCheckBoxGroup(1, 0, generalSettings, 1, generalGrp); generalGrid->addWidget(generals, 1, 0); addLabel(generalGrid, 2, 0, i18n("MountMan will not (un)mount the following mount-points:"), generalGrp); KonfiguratorEditBox *nonMountPoints = createEditBox("Advanced", "Nonmount Points", _NonMountPoints, generalGrp, false); generalGrid->addWidget(nonMountPoints, 2, 1); #ifdef BSD generals->find("AutoMount")->setEnabled(false); /* disable AutoMount on BSD */ #endif kgAdvancedLayout->addWidget(generalGrp, 0 , 0); // ----------------------- CONFIRMATIONS GROUPBOX ------------------------------- QGroupBox *confirmGrp = createFrame(i18n("Confirmations"), innerWidget); QGridLayout *confirmGrid = createGridLayout(confirmGrp); addLabel(confirmGrid, 0, 0, i18n("\nRequest user confirmation for the following operations:\n"), confirmGrp); KONFIGURATOR_CHECKBOX_PARAM confirmations[] = // cfg_class cfg_name default text restart ToolTip {{"Advanced", "Confirm Unempty Dir", _ConfirmUnemptyDir, i18n("Deleting non-empty folders"), false, ""}, {"Advanced", "Confirm Delete", _ConfirmDelete, i18n("Deleting files"), false, ""}, {"Advanced", "Confirm Copy", _ConfirmCopy, i18n("Copying files"), false, ""}, {"Advanced", "Confirm Move", _ConfirmMove, i18n("Moving files"), false, ""}, {"Advanced", "Confirm Feed to Listbox", _ConfirmFeedToListbox, i18n("Confirm feed to listbox"), false, i18n("Ask for a result name when feeding items to the listbox. By default the standard value is used.")}, {"Notification Messages", "Confirm Remove UserAction", true, i18n("Removing Useractions"), false, ""} }; KonfiguratorCheckBoxGroup *confWnd = createCheckBoxGroup(2, 0, confirmations, 6, confirmGrp); confirmGrid->addWidget(confWnd, 1, 0); kgAdvancedLayout->addWidget(confirmGrp, 1 , 0); // ------------------------ FINE-TUNING GROUPBOX -------------------------------- QGroupBox *fineTuneGrp = createFrame(i18n("Fine-Tuning"), innerWidget); QGridLayout *fineTuneGrid = createGridLayout(fineTuneGrp); fineTuneGrid->setAlignment(Qt::AlignLeft | Qt::AlignTop); QLabel *label = new QLabel(i18n("Icon cache size (KB):"), fineTuneGrp); label->setWhatsThis(i18n("The icon cache size influences how fast the contents of a panel can be displayed. However, too large a cache might consume your memory.")); fineTuneGrid->addWidget(label, 0, 0); KonfiguratorSpinBox *spinBox = createSpinBox("Advanced", "Icon Cache Size", _IconCacheSize, 1, 8192, fineTuneGrp, false); spinBox->setWhatsThis(i18n("The icon cache size influences how fast the contents of a panel can be displayed. However, too large a cache might consume your memory.")); spinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); fineTuneGrid->addWidget(spinBox, 0, 1); addLabel(fineTuneGrid, 1, 0, i18n("Arguments of updatedb:"), fineTuneGrp); KonfiguratorEditBox *updatedbArgs = createEditBox("Locate", "UpdateDB Arguments", "", fineTuneGrp, false); fineTuneGrid->addWidget(updatedbArgs, 1, 1); kgAdvancedLayout->addWidget(fineTuneGrp, 2 , 0); } diff --git a/krusader/Konfigurator/kgadvanced.h b/krusader/Konfigurator/kgadvanced.h index b9e586b9..6cbab0d5 100644 --- a/krusader/Konfigurator/kgadvanced.h +++ b/krusader/Konfigurator/kgadvanced.h @@ -1,44 +1,34 @@ -/*************************************************************************** - kgadvanced.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KGADVANCED_H #define KGADVANCED_H #include "konfiguratorpage.h" class KgAdvanced : public KonfiguratorPage { Q_OBJECT public: explicit KgAdvanced(bool first, QWidget* parent = 0); }; #endif /* __KGADVANCED_H__ */ diff --git a/krusader/Konfigurator/kgarchives.cpp b/krusader/Konfigurator/kgarchives.cpp index 6e7ce3f9..f4842103 100644 --- a/krusader/Konfigurator/kgarchives.cpp +++ b/krusader/Konfigurator/kgarchives.cpp @@ -1,143 +1,133 @@ -/*************************************************************************** - kgarchives.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kgarchives.h" // QtCore #include // QtWidgets #include #include #include #include #include "krresulttable.h" #include "krresulttabledialog.h" #include "searchobject.h" #include "../defaults.h" #include "../krglobal.h" #include "../Archive/krarchandler.h" KgArchives::KgArchives(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { QWidget *innerWidget = new QFrame(this); setWidget(innerWidget); setWidgetResizable(true); QGridLayout *kgArchivesLayout = new QGridLayout(innerWidget); kgArchivesLayout->setSpacing(6); // ------------------------ KRARC GROUPBOX -------------------------------- QGroupBox *krarcGrp = createFrame(i18n("krarc ioslave"), innerWidget); QGridLayout *krarcGrid = createGridLayout(krarcGrp); KONFIGURATOR_CHECKBOX_PARAM krarcOptions[] = // cfg_class cfg_name default text restart ToolTip { {"kio_krarc", "EnableWrite", false, i18n("Enable Write Support"), false, i18n("Enable writing to archives using the krarc ioslave.")} }; KonfiguratorCheckBoxGroup *krarcCheckBoxes = createCheckBoxGroup(1, 0, krarcOptions, 1, krarcGrp); krarcGrid->addWidget(krarcCheckBoxes, 1, 0); krarcGrid->addWidget( new QLabel(i18n("Caution when moving into archives:
" "Failure during the process might result in data loss.
" "Moving archives into themselves will delete them."), krarcGrp), 2, 0); kgArchivesLayout->addWidget(krarcGrp, 1 , 0); // ------------------------ BROWSE GROUPBOX -------------------------------- QGroupBox *browseGrp = createFrame(i18n("Archives handling"), innerWidget); QGridLayout *browseGrid = createGridLayout(browseGrp); KONFIGURATOR_CHECKBOX_PARAM browseOptions[] = // cfg_class cfg_name default text restart ToolTip { {"Archives", "ArchivesAsDirectories", _ArchivesAsDirectories, i18n("Browse Archives As Folders"), false, i18n("Krusader will browse archives as folders.")} }; KonfiguratorCheckBoxGroup *browseCheckBoxes = createCheckBoxGroup(1, 0, browseOptions, 1, browseGrp); browseGrid->addWidget(browseCheckBoxes, 1, 0); kgArchivesLayout->addWidget(browseGrp, 2 , 0); // ------------------------ FINE-TUNING GROUPBOX -------------------------------- QGroupBox *fineTuneGrp = createFrame(i18n("Fine-Tuning"), innerWidget); QGridLayout *fineTuneGrid = createGridLayout(fineTuneGrp); KONFIGURATOR_CHECKBOX_PARAM finetuners[] = // cfg_class cfg_name default text restart ToolTip { {"Archives", "Test Archives", _TestArchives, i18n("Test archive after packing"), false, i18n("Check the archive's integrity after packing it.")}, {"Archives", "Test Before Unpack", _TestBeforeUnpack, i18n("Test archive before unpacking"), false, i18n("Some corrupted archives might cause a crash; therefore, testing is suggested.")} }; KonfiguratorCheckBoxGroup *finetunes = createCheckBoxGroup(1, 0, finetuners, 2, fineTuneGrp); disableNonExistingPackers(); fineTuneGrid->addWidget(finetunes, 1, 0); kgArchivesLayout->addWidget(fineTuneGrp, 3 , 0); if (first) slotAutoConfigure(); } void KgArchives::slotAutoConfigure() { QPointer dlg = new KrResultTableDialog(this, KrResultTableDialog::Archiver, i18n("Search results"), i18n("Searching for packers..."), "utilities-file-archiver", i18n("Make sure to install new packers in your $PATH (e.g. /usr/bin)")); dlg->exec(); disableNonExistingPackers(); delete dlg; } void KgArchives::disableNonExistingPackers() { KConfigGroup group(krConfig, "Archives"); group.writeEntry("Supported Packers", KRarcHandler::supportedPackers()); } diff --git a/krusader/Konfigurator/kgarchives.h b/krusader/Konfigurator/kgarchives.h index 802708ef..c6292e08 100644 --- a/krusader/Konfigurator/kgarchives.h +++ b/krusader/Konfigurator/kgarchives.h @@ -1,50 +1,40 @@ -/*************************************************************************** - kgarchives.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KGARCHIVES_H #define KGARCHIVES_H #include "konfiguratorpage.h" class KgArchives : public KonfiguratorPage { Q_OBJECT public: explicit KgArchives(bool first, QWidget* parent = 0); public slots: void slotAutoConfigure(); protected: void disableNonExistingPackers(); }; #endif /* __KGARCHIVES_H__ */ diff --git a/krusader/Konfigurator/kgcolors.cpp b/krusader/Konfigurator/kgcolors.cpp index 2cb7a245..19eb04ca 100644 --- a/krusader/Konfigurator/kgcolors.cpp +++ b/krusader/Konfigurator/kgcolors.cpp @@ -1,715 +1,705 @@ -/*************************************************************************** - kgcolors.cpp - description - ------------------- - copyright : (C) 2004 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kgcolors.h" #include "../defaults.h" #include "../Panel/krcolorcache.h" #include "../Synchronizer/synchronizercolors.h" // QtCore #include #include // QtGui #include // QtWidgets #include #include #include #include #include #include #include KgColors::KgColors(bool first, QWidget* parent) : KonfiguratorPage(first, parent), offset(0), activeTabIdx(-1), inactiveTabIdx(-1), #ifdef SYNCHRONIZER_ENABLED synchronizerTabIdx(-1), #endif otherTabIdx(-1) { QWidget *innerWidget = new QFrame(this); setWidget(innerWidget); setWidgetResizable(true); QGridLayout *kgColorsLayout = new QGridLayout(innerWidget); kgColorsLayout->setSpacing(6); // -------------------------- GENERAL GROUPBOX ---------------------------------- QGroupBox *generalGrp = createFrame(i18n("General"), innerWidget); QGridLayout *generalGrid = createGridLayout(generalGrp); generalGrid->setSpacing(0); generalGrid->setContentsMargins(5, 5, 5, 5); KONFIGURATOR_CHECKBOX_PARAM generalSettings[] = // cfg_class cfg_name default text restart tooltip {{"Colors", "KDE Default", _KDEDefaultColors, i18n("Use the default KDE colors"), false, "

" + i18n("

Use KDE's global color configuration.

KDE System Settings -> Application Appearance -> Colors

") }, {"Colors", "Enable Alternate Background", _AlternateBackground, i18n("Use alternate background color"), false, i18n("

The background color and the alternate background color alternates line by line.

When you don't use the KDE default colors, you can configure the alternate colors in the colors box.

") }, {"Colors", "Show Current Item Always", _ShowCurrentItemAlways, i18n("Show current item even if not focused"), false, i18n("

Shows the last cursor position in the non active list panel.

This option is only available when you don't use the KDE default colors.

") }, {"Colors", "Dim Inactive Colors", _DimInactiveColors, i18n("Dim the colors of the inactive panel"), false, i18n("

The colors of the inactive panel are calculated by a dim color and a dim factor.

") } }; generals = createCheckBoxGroup(0, 2, generalSettings, sizeof(generalSettings) / sizeof(generalSettings[0]), generalGrp); generalGrid->addWidget(generals, 1, 0); generals->layout()->setSpacing(5); connect(generals->find("KDE Default"), SIGNAL(stateChanged(int)), this, SLOT(slotDisable())); connect(generals->find("Show Current Item Always"), SIGNAL(stateChanged(int)), this, SLOT(slotDisable())); connect(generals->find("Dim Inactive Colors"), SIGNAL(stateChanged(int)), this, SLOT(slotDisable())); kgColorsLayout->addWidget(generalGrp, 0 , 0, 1, 3); QWidget *hboxWidget = new QWidget(innerWidget); QHBoxLayout *hbox = new QHBoxLayout(hboxWidget); // -------------------------- COLORS GROUPBOX ---------------------------------- QGroupBox *colorsFrameGrp = createFrame(i18n("Colors"), hboxWidget); QGridLayout *colorsFrameGrid = createGridLayout(colorsFrameGrp); colorsFrameGrid->setSpacing(0); colorsFrameGrid->setContentsMargins(3, 3, 3, 3); colorTabWidget = new QTabWidget(colorsFrameGrp); colorsGrp = new QWidget(colorTabWidget); activeTabIdx = colorTabWidget->addTab(colorsGrp, i18n("Active")); colorsGrid = new QGridLayout(colorsGrp); colorsGrid->setSpacing(0); colorsGrid->setContentsMargins(2, 2, 2, 2); ADDITIONAL_COLOR transparent = { i18n("Transparent"), Qt::white, "transparent" }; QPalette p = QGuiApplication::palette(); addColorSelector("Foreground", i18n("Foreground:"), p.color(QPalette::Active, QPalette::Text)); addColorSelector("Directory Foreground", i18n("Folder foreground:"), getColorSelector("Foreground")->getColor(), i18n("Same as foreground")); addColorSelector("Executable Foreground", i18n("Executable foreground:"), getColorSelector("Foreground")->getColor(), i18n("Same as foreground")); addColorSelector("Symlink Foreground", i18n("Symbolic link foreground:"), getColorSelector("Foreground")->getColor(), i18n("Same as foreground")); addColorSelector("Invalid Symlink Foreground", i18n("Invalid symlink foreground:"), getColorSelector("Foreground")->getColor(), i18n("Same as foreground")); addColorSelector("Background", i18n("Background:"), p.color(QPalette::Active, QPalette::Base)); ADDITIONAL_COLOR sameAsBckgnd = { i18n("Same as background"), getColorSelector("Background")->getColor(), "Background" }; addColorSelector("Alternate Background", i18n("Alternate background:"), p.color(QPalette::Active, QPalette::AlternateBase), "", &sameAsBckgnd, 1); addColorSelector("Marked Foreground", i18n("Selected foreground:"), p.color(QPalette::Active, QPalette::HighlightedText), "", &transparent, 1); addColorSelector("Marked Background", i18n("Selected background:"), p.color(QPalette::Active, QPalette::Highlight), "", &sameAsBckgnd, 1); ADDITIONAL_COLOR sameAsAltern = { i18n("Same as alt. background"), getColorSelector("Alternate Background")->getColor(), "Alternate Background" }; addColorSelector("Alternate Marked Background", i18n("Alternate selected background:"), getColorSelector("Marked Background")->getColor(), i18n("Same as selected background"), &sameAsAltern, 1); addColorSelector("Current Foreground", i18n("Current foreground:"), Qt::white, i18n("Not used")); ADDITIONAL_COLOR sameAsMarkedForegnd = { i18n("Same as selected foreground"), getColorSelector("Marked Foreground")->getColor(), "Marked Foreground" }; addColorSelector("Marked Current Foreground", i18n("Selected current foreground:"), Qt::white, i18n("Not used"), &sameAsMarkedForegnd, 1); addColorSelector("Current Background", i18n("Current background:"), Qt::white, i18n("Not used"), &sameAsBckgnd, 1); colorsGrid->addWidget(createSpacer(colorsGrp), itemList.count() - offset, 1); connect(getColorSelector("Foreground"), SIGNAL(colorChanged()), this, SLOT(slotForegroundChanged())); connect(getColorSelector("Background"), SIGNAL(colorChanged()), this, SLOT(slotBackgroundChanged())); connect(getColorSelector("Alternate Background"), SIGNAL(colorChanged()), this, SLOT(slotAltBackgroundChanged())); connect(getColorSelector("Marked Background"), SIGNAL(colorChanged()), this, SLOT(slotMarkedBackgroundChanged())); inactiveColorStack = new QStackedWidget(colorTabWidget); inactiveTabIdx = colorTabWidget->addTab(inactiveColorStack, i18n("Inactive")); colorsGrp = normalInactiveWidget = new QWidget(inactiveColorStack); colorsGrid = new QGridLayout(normalInactiveWidget); colorsGrid->setSpacing(0); colorsGrid->setContentsMargins(2, 2, 2, 2); offset = endOfActiveColors = itemList.count(); addColorSelector("Inactive Foreground", i18n("Foreground:"), getColorSelector("Foreground")->getColor(), i18n("Same as active")); ADDITIONAL_COLOR sameAsInactForegnd = { i18n("Same as foreground"), getColorSelector("Inactive Foreground")->getColor(), "Inactive Foreground" }; addColorSelector("Inactive Directory Foreground", i18n("Folder foreground:"), getColorSelector("Directory Foreground")->getColor(), i18n("Same as active"), &sameAsInactForegnd, 1); addColorSelector("Inactive Executable Foreground", i18n("Executable foreground:"), getColorSelector("Executable Foreground")->getColor(), i18n("Same as active"), &sameAsInactForegnd, 1); addColorSelector("Inactive Symlink Foreground", i18n("Symbolic link foreground:"), getColorSelector("Symlink Foreground")->getColor(), i18n("Same as active"), &sameAsInactForegnd, 1); addColorSelector("Inactive Invalid Symlink Foreground", i18n("Invalid symlink foreground:"), getColorSelector("Invalid Symlink Foreground")->getColor(), i18n("Same as active"), &sameAsInactForegnd, 1); addColorSelector("Inactive Background", i18n("Background:"), getColorSelector("Background")->getColor(), i18n("Same as active")); ADDITIONAL_COLOR sameAsInactBckgnd = { i18n("Same as background"), getColorSelector("Inactive Background")->getColor(), "Inactive Background" }; addColorSelector("Inactive Alternate Background", i18n("Alternate background:"), getColorSelector("Alternate Background")->getColor(), i18n("Same as active"), &sameAsInactBckgnd, 1); addColorSelector("Inactive Marked Foreground", i18n("Selected foreground:"), getColorSelector("Marked Foreground")->getColor(), i18n("Same as active"), &transparent, 1); addColorSelector("Inactive Marked Background", i18n("Selected background:"), getColorSelector("Marked Background")->getColor(), i18n("Same as active"), &sameAsInactBckgnd, 1); ADDITIONAL_COLOR sameAsInactAltern[] = {{ i18n("Same as alt. background"), getColorSelector("Inactive Alternate Background")->getColor(), "Inactive Alternate Background" }, { i18n("Same as selected background"), getColorSelector("Inactive Marked Background")->getColor(), "Inactive Marked Background" } }; addColorSelector("Inactive Alternate Marked Background", i18n("Alternate selected background:"), getColorSelector("Alternate Marked Background")->getColor(), i18n("Same as active"), sameAsInactAltern, 2); addColorSelector("Inactive Current Foreground", i18n("Current foreground:"), getColorSelector("Current Foreground")->getColor(), i18n("Same as active")); ADDITIONAL_COLOR sameAsInactMarkedForegnd = { i18n("Same as selected foreground"), getColorSelector("Inactive Marked Foreground")->getColor(), "Inactive Marked Foreground" }; addColorSelector("Inactive Marked Current Foreground", i18n("Selected current foreground:"), getColorSelector("Marked Current Foreground")->getColor(), i18n("Same as active"), &sameAsInactMarkedForegnd, 1); addColorSelector("Inactive Current Background", i18n("Current background:"), getColorSelector("Current Background")->getColor(), i18n("Same as active"), &sameAsInactBckgnd, 1); colorsGrid->addWidget(createSpacer(normalInactiveWidget), itemList.count() - offset, 1); connect(getColorSelector("Inactive Foreground"), SIGNAL(colorChanged()), this, SLOT(slotInactiveForegroundChanged())); connect(getColorSelector("Inactive Background"), SIGNAL(colorChanged()), this, SLOT(slotInactiveBackgroundChanged())); connect(getColorSelector("Inactive Alternate Background"), SIGNAL(colorChanged()), this, SLOT(slotInactiveAltBackgroundChanged())); connect(getColorSelector("Inactive Marked Background"), SIGNAL(colorChanged()), this, SLOT(slotInactiveMarkedBackgroundChanged())); offset = endOfPanelColors = itemList.count(); inactiveColorStack->addWidget(normalInactiveWidget); colorsGrp = dimmedInactiveWidget = new QWidget(inactiveColorStack); colorsGrid = new QGridLayout(dimmedInactiveWidget); colorsGrid->setSpacing(0); colorsGrid->setContentsMargins(2, 2, 2, 2); addColorSelector("Dim Target Color", i18n("Dim target color:"), Qt::black); int index = itemList.count() - offset; labelList.append(addLabel(colorsGrid, index, 0, i18n("Dim factor:"), colorsGrp)); dimFactor = createSpinBox("Colors", "Dim Factor", 80, 0, 100, colorsGrp); dimFactor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); colorsGrid->addWidget(dimFactor, index++, 1); colorsGrid->addWidget(createSpacer(dimmedInactiveWidget), itemList.count() + 1 - offset, 1); inactiveColorStack->addWidget(dimmedInactiveWidget); inactiveColorStack->setCurrentWidget(normalInactiveWidget); ADDITIONAL_COLOR KDEDefaultBase = { i18n("KDE default"), p.color(QPalette::Active, QPalette::Base), "KDE default" }; ADDITIONAL_COLOR KDEDefaultFore = { i18n("KDE default"), p.color(QPalette::Active, QPalette::Text), "KDE default" }; #ifdef SYNCHRONIZER_ENABLED colorsGrp = new QWidget(colorTabWidget); synchronizerTabIdx = colorTabWidget->addTab(colorsGrp, i18n("Synchronizer")); colorsGrid = new QGridLayout(colorsGrp); colorsGrid->setSpacing(0); colorsGrid->setContentsMargins(2, 2, 2, 2); offset = endOfPanelColors = itemList.count(); DECLARE_SYNCHRONIZER_BACKGROUND_DEFAULTS; DECLARE_SYNCHRONIZER_FOREGROUND_DEFAULTS; addColorSelector("Synchronizer Equals Foreground", i18n("Equals foreground:"), SYNCHRONIZER_FOREGROUND_DEFAULTS[0], QString(), &KDEDefaultFore, 1); addColorSelector("Synchronizer Equals Background", i18n("Equals background:"), SYNCHRONIZER_BACKGROUND_DEFAULTS[0], QString(), &KDEDefaultBase, 1); addColorSelector("Synchronizer Differs Foreground", i18n("Differing foreground:"), SYNCHRONIZER_FOREGROUND_DEFAULTS[1], QString(), &KDEDefaultFore, 1); addColorSelector("Synchronizer Differs Background", i18n("Differing background:"), SYNCHRONIZER_BACKGROUND_DEFAULTS[1], QString(), &KDEDefaultBase, 1); addColorSelector("Synchronizer LeftCopy Foreground", i18n("Copy to left foreground:"), SYNCHRONIZER_FOREGROUND_DEFAULTS[2], QString(), &KDEDefaultFore, 1); addColorSelector("Synchronizer LeftCopy Background", i18n("Copy to left background:"), SYNCHRONIZER_BACKGROUND_DEFAULTS[2], QString(), &KDEDefaultBase, 1); addColorSelector("Synchronizer RightCopy Foreground", i18n("Copy to right foreground:"), SYNCHRONIZER_FOREGROUND_DEFAULTS[3], QString(), &KDEDefaultFore, 1); addColorSelector("Synchronizer RightCopy Background", i18n("Copy to right background:"), SYNCHRONIZER_BACKGROUND_DEFAULTS[3], QString(), &KDEDefaultBase, 1); addColorSelector("Synchronizer Delete Foreground", i18n("Delete foreground:"), SYNCHRONIZER_FOREGROUND_DEFAULTS[4], QString(), &KDEDefaultFore, 1); addColorSelector("Synchronizer Delete Background", i18n("Delete background:"), SYNCHRONIZER_BACKGROUND_DEFAULTS[4], QString(), &KDEDefaultBase, 1); colorsGrid->addWidget(createSpacer(colorsGrp), itemList.count() - offset, 1); #endif colorsGrp = new QWidget(colorTabWidget); otherTabIdx = colorTabWidget->addTab(colorsGrp, i18n("Other")); colorsGrid = new QGridLayout(colorsGrp); colorsGrid->setSpacing(0); colorsGrid->setContentsMargins(2, 2, 2, 2); offset = endOfPanelColors = itemList.count(); addColorSelector("Quicksearch Match Foreground", i18n("Quicksearch, match foreground:"), Qt::black, QString(), &KDEDefaultFore, 1); addColorSelector("Quicksearch Match Background", i18n("Quicksearch, match background:"), QColor(192, 255, 192), QString(), &KDEDefaultBase, 1); addColorSelector("Quicksearch Non-match Foreground", i18n("Quicksearch, non-match foreground:"), Qt::black, QString(), &KDEDefaultFore, 1); addColorSelector("Quicksearch Non-match Background", i18n("Quicksearch, non-match background:"), QColor(255, 192, 192), QString(), &KDEDefaultBase, 1); ADDITIONAL_COLOR KDEDefaultWindowFore = { i18n("KDE default"), p.color(QPalette::Active, QPalette::WindowText), "KDE default" }; ADDITIONAL_COLOR KDEDefaultWindowBack = { i18n("KDE default"), p.color(QPalette::Active, QPalette::Window), "KDE default" }; addColorSelector("Statusbar Foreground Active", i18n("Statusbar, active foreground:"), p.color(QPalette::Active, QPalette::HighlightedText), QString(), &KDEDefaultWindowFore, 1); addColorSelector("Statusbar Background Active", i18n("Statusbar, active background:"), p.color(QPalette::Active, QPalette::Highlight), QString(), &KDEDefaultWindowBack, 1); addColorSelector("Statusbar Foreground Inactive", i18n("Statusbar, inactive foreground:"), p.color(QPalette::Inactive, QPalette::Text), QString(), &KDEDefaultWindowFore, 1); addColorSelector("Statusbar Background Inactive", i18n("Statusbar, inactive background:"), p.color(QPalette::Inactive, QPalette::Base), QString(), &KDEDefaultWindowBack, 1); colorsGrid->addWidget(createSpacer(colorsGrp), itemList.count() - offset, 1); colorsFrameGrid->addWidget(colorTabWidget, 0, 0); hbox->addWidget(colorsFrameGrp); // -------------------------- PREVIEW GROUPBOX ---------------------------------- previewGrp = createFrame(i18n("Preview"), hboxWidget); previewGrid = createGridLayout(previewGrp); preview = new KrTreeWidget(previewGrp); preview->setBackgroundRole(QPalette::Window); preview->setAutoFillBackground(true); QStringList labels; labels << i18n("Colors"); preview->setHeaderLabels(labels); preview->header()->setSortIndicatorShown(false); preview->setSortingEnabled(false); preview->setEnabled(false); previewGrid->addWidget(preview, 0 , 0); hbox->addWidget(previewGrp); connect(generals->find("Enable Alternate Background"), SIGNAL(stateChanged(int)), this, SLOT(generatePreview())); connect(colorTabWidget, SIGNAL(currentChanged(int)), this, SLOT(generatePreview())); connect(dimFactor, SIGNAL(valueChanged(int)), this, SLOT(generatePreview())); kgColorsLayout->addWidget(hboxWidget, 1 , 0, 1, 3); importBtn = new QPushButton(i18n("Import color-scheme"), innerWidget); kgColorsLayout->addWidget(importBtn, 2, 0); exportBtn = new QPushButton(i18n("Export color-scheme"), innerWidget); kgColorsLayout->addWidget(exportBtn, 2, 1); kgColorsLayout->addWidget(createSpacer(innerWidget), 2, 2); connect(importBtn, SIGNAL(clicked()), this, SLOT(slotImportColors())); connect(exportBtn, SIGNAL(clicked()), this, SLOT(slotExportColors())); slotDisable(); } int KgColors::addColorSelector(QString cfgName, QString name, QColor defaultValue, QString dfltName, ADDITIONAL_COLOR *addColor, int addColNum) { int index = itemList.count() - offset; labelList.append(addLabel(colorsGrid, index, 0, name, colorsGrp)); KonfiguratorColorChooser *chooser = createColorChooser("Colors", cfgName, defaultValue, colorsGrp, false, addColor, addColNum); chooser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); if (!dfltName.isEmpty()) chooser->setDefaultText(dfltName); colorsGrid->addWidget(chooser, index, 1); connect(chooser, SIGNAL(colorChanged()), this, SLOT(generatePreview())); if (!offset) connect(chooser, SIGNAL(colorChanged()), this, SLOT(slotActiveChanged())); itemList.append(chooser); itemNames.append(cfgName); return index; } KonfiguratorColorChooser *KgColors::getColorSelector(QString name) { QList::iterator it; int position = 0; for (it = itemNames.begin(); it != itemNames.end(); it++, position++) if (*it == name) return itemList.at(position); return 0; } QLabel *KgColors::getSelectorLabel(QString name) { QList::iterator it; int position = 0; for (it = itemNames.begin(); it != itemNames.end(); it++, position++) if (*it == name) return labelList.at(position); return 0; } void KgColors::slotDisable() { bool enabled = generals->find("KDE Default")->isChecked(); importBtn->setEnabled(!enabled); exportBtn->setEnabled(!enabled); for (int i = 0; i < labelList.count() && i < endOfPanelColors ; i++) labelList.at(i)->setEnabled(!enabled); for (int j = 0; j < itemList.count() && j < endOfPanelColors ; j++) itemList.at(j)->setEnabled(!enabled); generals->find("Enable Alternate Background")->setEnabled(enabled); generals->find("Show Current Item Always")->setEnabled(!enabled); generals->find("Dim Inactive Colors")->setEnabled(!enabled); bool dimmed = !enabled && generals->find("Dim Inactive Colors")->isChecked(); if (dimmed) inactiveColorStack->setCurrentWidget(dimmedInactiveWidget); else inactiveColorStack->setCurrentWidget(normalInactiveWidget); enabled = enabled || !generals->find("Show Current Item Always")->isChecked(); getColorSelector("Inactive Current Foreground")->setEnabled(!enabled); getColorSelector("Inactive Current Background")->setEnabled(!enabled); generatePreview(); } void KgColors::slotActiveChanged() { for (int i = 0; i != endOfActiveColors; i++) itemList.at(endOfActiveColors + i)->setDefaultColor(itemList.at(i)->getColor()); } void KgColors::slotForegroundChanged() { QColor color = getColorSelector("Foreground")->getColor(); getColorSelector("Directory Foreground")->setDefaultColor(color); getColorSelector("Executable Foreground")->setDefaultColor(color); getColorSelector("Symlink Foreground")->setDefaultColor(color); getColorSelector("Invalid Symlink Foreground")->setDefaultColor(color); } void KgColors::slotBackgroundChanged() { QColor color = getColorSelector("Background")->getColor(); getColorSelector("Alternate Background")->changeAdditionalColor(0, color); getColorSelector("Marked Background")->changeAdditionalColor(0, color); getColorSelector("Current Background")->changeAdditionalColor(0, color); } void KgColors::slotAltBackgroundChanged() { QColor color = getColorSelector("Alternate Background")->getColor(); getColorSelector("Alternate Marked Background")->changeAdditionalColor(0, color); } void KgColors::slotMarkedBackgroundChanged() { QColor color = getColorSelector("Marked Background")->getColor(); getColorSelector("Alternate Marked Background")->setDefaultColor(color); } void KgColors::slotInactiveForegroundChanged() { QColor color = getColorSelector("Inactive Foreground")->getColor(); getColorSelector("Inactive Directory Foreground")->changeAdditionalColor(0, color); getColorSelector("Inactive Executable Foreground")->changeAdditionalColor(0, color); getColorSelector("Inactive Symlink Foreground")->changeAdditionalColor(0, color); getColorSelector("Inactive Invalid Symlink Foreground")->changeAdditionalColor(0, color); } void KgColors::slotInactiveBackgroundChanged() { QColor color = getColorSelector("Inactive Background")->getColor(); getColorSelector("Inactive Alternate Background")->changeAdditionalColor(0, color); getColorSelector("Inactive Marked Background")->changeAdditionalColor(0, color); getColorSelector("Inactive Current Background")->changeAdditionalColor(0, color); } void KgColors::slotInactiveAltBackgroundChanged() { QColor color = getColorSelector("Inactive Alternate Background")->getColor(); getColorSelector("Inactive Alternate Marked Background")->changeAdditionalColor(0, color); } void KgColors::slotInactiveMarkedBackgroundChanged() { QColor color = getColorSelector("Inactive Marked Background")->getColor(); getColorSelector("Inactive Alternate Marked Background")->changeAdditionalColor(1, color); } void KgColors::setColorWithDimming(PreviewItem * item, QColor foreground, QColor background, bool dimmed) { if (dimmed && dimFactor->value() < 100) { int dim = dimFactor->value(); QColor dimColor = getColorSelector("Dim Target Color")->getColor(); foreground = QColor((dimColor.red() * (100 - dim) + foreground.red() * dim) / 100, (dimColor.green() * (100 - dim) + foreground.green() * dim) / 100, (dimColor.blue() * (100 - dim) + foreground.blue() * dim) / 100); background = QColor((dimColor.red() * (100 - dim) + background.red() * dim) / 100, (dimColor.green() * (100 - dim) + background.green() * dim) / 100, (dimColor.blue() * (100 - dim) + background.blue() * dim) / 100); } item->setColor(foreground, background); } void KgColors::generatePreview() { const int currentPage = colorTabWidget->currentIndex(); preview->clear(); if (currentPage == activeTabIdx || currentPage == inactiveTabIdx) { PreviewItem *pwMarkCur = new PreviewItem(preview, i18n("Selected + Current")); PreviewItem *pwMark2 = new PreviewItem(preview, i18n("Selected 2")); PreviewItem *pwMark1 = new PreviewItem(preview, i18n("Selected 1")); PreviewItem *pwCurrent = new PreviewItem(preview, i18n("Current")); PreviewItem *pwInvLink = new PreviewItem(preview, i18n("Invalid symlink")); PreviewItem *pwSymLink = new PreviewItem(preview, i18n("Symbolic link")); PreviewItem *pwApp = new PreviewItem(preview, i18n("Application")); PreviewItem *pwFile = new PreviewItem(preview, i18n("File")); PreviewItem *pwDir = new PreviewItem(preview, i18n("Folder")); bool isActive = currentPage == 0; // create local color cache instance, which does NOT affect the color cache instance using to paint the panels KrColorCache colCache; // create local color settings instance, which initially contains the setings from krConfig KrColorSettings colorSettings; // copy over local settings to color settings instance, which does not affect the persisted krConfig settings QList names = KrColorSettings::getColorNames(); for (QList::Iterator it = names.begin(); it != names.end(); ++it) { KonfiguratorColorChooser * chooser = getColorSelector(*it); if (!chooser) continue; colorSettings.setColorTextValue(*it, chooser->getValue()); if (chooser->isValueRGB()) colorSettings.setColorValue(*it, chooser->getColor()); else colorSettings.setColorValue(*it, QColor()); } colorSettings.setBoolValue("KDE Default", generals->find("KDE Default")->isChecked()); colorSettings.setBoolValue("Enable Alternate Background", generals->find("Enable Alternate Background")->isChecked()); colorSettings.setBoolValue("Show Current Item Always", generals->find("Show Current Item Always")->isChecked()); colorSettings.setBoolValue("Dim Inactive Colors", generals->find("Dim Inactive Colors")->isChecked()); colorSettings.setNumValue("Dim Factor", dimFactor->value()); // let the color cache use the local color settings colCache.setColors(colorSettings); // ask the local color cache for certain color groups and use them to color the preview KrColorGroup cg; // setting the background color colCache.getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, false, false)); QPalette pal = preview->palette(); pal.setColor(QPalette::Base, cg.background()); preview->setPalette(pal); colCache.getColors(cg, KrColorItemType(KrColorItemType::Directory, false, isActive, false, false)); pwDir->setColor(cg.text(), cg.background()); colCache.getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, false, false)); pwFile->setColor(cg.text(), cg.background()); colCache.getColors(cg, KrColorItemType(KrColorItemType::Executable, false, isActive, false, false)); pwApp->setColor(cg.text(), cg.background()); colCache.getColors(cg, KrColorItemType(KrColorItemType::Symlink, true, isActive, false, false)); pwSymLink->setColor(cg.text(), cg.background()); colCache.getColors(cg, KrColorItemType(KrColorItemType::InvalidSymlink, false, isActive, false, false)); pwInvLink->setColor(cg.text(), cg.background()); colCache.getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, true, false)); pwCurrent->setColor(cg.text(), cg.background()); colCache.getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, false, true)); pwMark1->setColor(cg.highlightedText(), cg.highlight()); colCache.getColors(cg, KrColorItemType(KrColorItemType::File, true, isActive, false, true)); pwMark2->setColor(cg.highlightedText(), cg.highlight()); colCache.getColors(cg, KrColorItemType(KrColorItemType::File, false, isActive, true, true)); pwMarkCur->setColor(cg.highlightedText(), cg.highlight()); } #ifdef SYNCHRONIZER_ENABLED else if (currentPage == synchronizerTabIdx) { PreviewItem *pwDelete = new PreviewItem(preview, i18n("Delete")); PreviewItem *pwRightCopy = new PreviewItem(preview, i18n("Copy to right")); PreviewItem *pwLeftCopy = new PreviewItem(preview, i18n("Copy to left")); PreviewItem *pwDiffers = new PreviewItem(preview, i18n("Differing")); PreviewItem *pwEquals = new PreviewItem(preview, i18n("Equals")); pwEquals->setColor(getColorSelector("Synchronizer Equals Foreground")->getColor(), getColorSelector("Synchronizer Equals Background")->getColor()); pwDiffers->setColor(getColorSelector("Synchronizer Differs Foreground")->getColor(), getColorSelector("Synchronizer Differs Background")->getColor()); pwLeftCopy->setColor(getColorSelector("Synchronizer LeftCopy Foreground")->getColor(), getColorSelector("Synchronizer LeftCopy Background")->getColor()); pwRightCopy->setColor(getColorSelector("Synchronizer RightCopy Foreground")->getColor(), getColorSelector("Synchronizer RightCopy Background")->getColor()); pwDelete->setColor(getColorSelector("Synchronizer Delete Foreground")->getColor(), getColorSelector("Synchronizer Delete Background")->getColor()); } #endif else if (currentPage == otherTabIdx) { PreviewItem *pwNonMatch = new PreviewItem(preview, i18n("Quicksearch non-match")); PreviewItem *pwMatch = new PreviewItem(preview, i18n("Quicksearch match")); pwMatch->setColor(getColorSelector("Quicksearch Match Foreground")->getColor(), getColorSelector("Quicksearch Match Background")->getColor()); pwNonMatch->setColor(getColorSelector("Quicksearch Non-match Foreground")->getColor(), getColorSelector("Quicksearch Non-match Background")->getColor()); PreviewItem *pwStatusActive = new PreviewItem(preview, i18n("Statusbar active")); PreviewItem *pwStatusInactive = new PreviewItem(preview, i18n("Statusbar inactive")); pwStatusActive->setColor(getColorSelector("Statusbar Foreground Active")->getColor(), getColorSelector("Statusbar Background Active")->getColor()); pwStatusInactive->setColor(getColorSelector("Statusbar Foreground Inactive")->getColor(), getColorSelector("Statusbar Background Inactive")->getColor()); } } bool KgColors::apply() { bool result = KonfiguratorPage::apply(); KrColorCache::getColorCache().refreshColors(); return result; } void KgColors::slotImportColors() { // find $KDEDIR/share/apps/krusader QString basedir= QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("total_commander.keymap")); basedir = QFileInfo(basedir).absolutePath(); // let the user select a file to load QString file = QFileDialog::getOpenFileName(0, i18n("Select a color-scheme file"), basedir, QStringLiteral("*.color")); if (file.isEmpty()) { return; } QFile f(file); if (!f.open(QIODevice::ReadOnly)) { KMessageBox::error(this, i18n("Error: unable to read from file"), i18n("Error")); return; } QDataStream stream(&f); // ok, import away deserialize(stream); generatePreview(); } void KgColors::slotExportColors() { QString file = QFileDialog::getSaveFileName(0, i18n("Select a color scheme file"), QString(), QStringLiteral("*")); if (file.isEmpty()) { return; } QFile f(file); if (f.exists() && KMessageBox::warningContinueCancel(this, i18n("File %1 already exists. Are you sure you want to overwrite it?", file), i18n("Warning"), KStandardGuiItem::overwrite()) != KMessageBox::Continue) return; if (!f.open(QIODevice::WriteOnly)) { KMessageBox::error(this, i18n("Error: unable to write to file"), i18n("Error")); return; } QDataStream stream(&f); serialize(stream); } void KgColors::serialize(QDataStream & stream) { serializeItem(stream, "Alternate Background"); serializeItem(stream, "Alternate Marked Background"); serializeItem(stream, "Background"); serializeItem(stream, "Current Background"); serializeItem(stream, "Current Foreground"); serializeItem(stream, "Enable Alternate Background"); serializeItem(stream, "Foreground"); serializeItem(stream, "Directory Foreground"); serializeItem(stream, "Executable Foreground"); serializeItem(stream, "Symlink Foreground"); serializeItem(stream, "Invalid Symlink Foreground"); serializeItem(stream, "Inactive Alternate Background"); serializeItem(stream, "Inactive Alternate Marked Background"); serializeItem(stream, "Inactive Background"); serializeItem(stream, "Inactive Current Foreground"); serializeItem(stream, "Inactive Current Background"); serializeItem(stream, "Inactive Marked Background"); serializeItem(stream, "Inactive Marked Current Foreground"); serializeItem(stream, "Inactive Marked Foreground"); serializeItem(stream, "Inactive Foreground"); serializeItem(stream, "Inactive Directory Foreground"); serializeItem(stream, "Inactive Executable Foreground"); serializeItem(stream, "Inactive Symlink Foreground"); serializeItem(stream, "Inactive Invalid Symlink Foreground"); serializeItem(stream, "Dim Inactive Colors"); serializeItem(stream, "Dim Target Color"); serializeItem(stream, "Dim Factor"); serializeItem(stream, "KDE Default"); serializeItem(stream, "Marked Background"); serializeItem(stream, "Marked Current Foreground"); serializeItem(stream, "Marked Foreground"); serializeItem(stream, "Show Current Item Always"); #ifdef SYNCHRONIZER_ENABLED serializeItem(stream, "Synchronizer Equals Foreground"); serializeItem(stream, "Synchronizer Equals Background"); serializeItem(stream, "Synchronizer Differs Foreground"); serializeItem(stream, "Synchronizer Differs Background"); serializeItem(stream, "Synchronizer LeftCopy Foreground"); serializeItem(stream, "Synchronizer LeftCopy Background"); serializeItem(stream, "Synchronizer RightCopy Foreground"); serializeItem(stream, "Synchronizer RightCopy Background"); serializeItem(stream, "Synchronizer Delete Foreground"); serializeItem(stream, "Synchronizer Delete Background"); #endif serializeItem(stream, "Quicksearch Match Foreground"); serializeItem(stream, "Quicksearch Match Background"); serializeItem(stream, "Quicksearch Non-match Foreground"); serializeItem(stream, "Quicksearch Non-match Background"); serializeItem(stream, "Statusbar Foreground Active"); serializeItem(stream, "Statusbar Background Active"); serializeItem(stream, "Statusbar Foreground Inactive"); serializeItem(stream, "Statusbar Background Inactive"); stream << QString("") << QString(""); } void KgColors::deserialize(QDataStream & stream) { for (;;) { QString name; QString value; stream >> name >> value; if (name.isEmpty()) break; if (name == "KDE Default" || name == "Enable Alternate Background" || name == "Show Current Item Always" || name == "Dim Inactive Colors") { bool bValue = false; value = value.toLower(); if (value == "true" || value == "yes" || value == "on" || value == "1") bValue = true; generals->find(name)->setChecked(bValue); continue; } if (name == "Dim Factor") { dimFactor->setValue(value.toInt()); continue; } KonfiguratorColorChooser *selector = getColorSelector(name); if (selector == 0) break; selector->setValue(value); } } void KgColors::serializeItem(class QDataStream & stream, const char * name) { stream << QString(name); if (strcmp(name, "KDE Default") == 0 || strcmp(name, "Enable Alternate Background") == 0 || strcmp(name, "Show Current Item Always") == 0 || strcmp(name, "Dim Inactive Colors") == 0) { bool bValue = generals->find(name)->isChecked(); stream << QString(bValue ? "true" : "false"); } else if (strcmp(name, "Dim Factor") == 0) stream << QString::number(dimFactor->value()); else { KonfiguratorColorChooser *selector = getColorSelector(name); stream << selector->getValue(); } } diff --git a/krusader/Konfigurator/kgcolors.h b/krusader/Konfigurator/kgcolors.h index 58654942..7dc8b3de 100644 --- a/krusader/Konfigurator/kgcolors.h +++ b/krusader/Konfigurator/kgcolors.h @@ -1,150 +1,140 @@ -/*************************************************************************** - kgcolors.h - description - ------------------- - copyright : (C) 2004 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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 = 0); virtual bool apply() Q_DECL_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(QString cfgName, QString name, QColor defaultValue, QString dfltName = QString(), ADDITIONAL_COLOR *addColor = 0, int addColNum = 0); KonfiguratorColorChooser *getColorSelector(QString name); QLabel *getSelectorLabel(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, QString name) : QTreeWidgetItem() { setText(0, name); defaultBackground = QColor(255, 255, 255); defaultForeground = QColor(0, 0, 0); label = name; parent->insertTopLevelItem(0, this); } void setColor(QColor foregnd, 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.cpp b/krusader/Konfigurator/kgdependencies.cpp index 9cc2bf58..03cf737c 100644 --- a/krusader/Konfigurator/kgdependencies.cpp +++ b/krusader/Konfigurator/kgdependencies.cpp @@ -1,183 +1,173 @@ -/*************************************************************************** - kgdependencies.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kgdependencies.h" #include "../krservices.h" #include "../krglobal.h" // QtCore #include // QtWidgets #include #include #include #include #include #include #define PAGE_GENERAL 0 #define PAGE_PACKERS 1 #define PAGE_CHECKSUM 2 KgDependencies::KgDependencies(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { QGridLayout *kgDependenciesLayout = new QGridLayout(this); kgDependenciesLayout->setSpacing(6); // ---------------------------- GENERAL TAB ------------------------------------- tabWidget = new QTabWidget(this); QWidget *general_tab = new QWidget(tabWidget); QScrollArea* general_scroll = new QScrollArea(tabWidget); general_scroll->setFrameStyle(QFrame::NoFrame); general_scroll->setWidget(general_tab); // this also sets scrollacrea as the new parent for widget general_scroll->setWidgetResizable(true); // let the widget use every space available tabWidget->addTab(general_scroll, i18n("General")); QGridLayout *pathsGrid = new QGridLayout(general_tab); pathsGrid->setSpacing(6); pathsGrid->setContentsMargins(11, 11, 11, 11); pathsGrid->setAlignment(Qt::AlignTop); addApplication("kget", pathsGrid, 0, general_tab, PAGE_GENERAL); addApplication("mailer", pathsGrid, 1, general_tab, PAGE_GENERAL); addApplication("diff utility", pathsGrid, 2, general_tab, PAGE_GENERAL); addApplication("krename", pathsGrid, 3, general_tab, PAGE_GENERAL); addApplication("locate", pathsGrid, 4, general_tab, PAGE_GENERAL); addApplication("mount", pathsGrid, 5, general_tab, PAGE_GENERAL); addApplication("umount", pathsGrid, 6, general_tab, PAGE_GENERAL); addApplication("updatedb", pathsGrid, 7, general_tab, PAGE_GENERAL); // ---------------------------- PACKERS TAB ------------------------------------- QWidget *packers_tab = new QWidget(tabWidget); QScrollArea* packers_scroll = new QScrollArea(tabWidget); packers_scroll->setFrameStyle(QFrame::NoFrame); packers_scroll->setWidget(packers_tab); // this also sets scrollacrea as the new parent for widget packers_scroll->setWidgetResizable(true); // let the widget use every space available tabWidget->addTab(packers_scroll, i18n("Packers")); QGridLayout *archGrid1 = new QGridLayout(packers_tab); archGrid1->setSpacing(6); archGrid1->setContentsMargins(11, 11, 11, 11); archGrid1->setAlignment(Qt::AlignTop); addApplication("7z", archGrid1, 0, packers_tab, PAGE_PACKERS, "7za"); addApplication("arj", archGrid1, 1, packers_tab, PAGE_PACKERS); addApplication("bzip2", archGrid1, 2, packers_tab, PAGE_PACKERS); addApplication("cpio", archGrid1, 3, packers_tab, PAGE_PACKERS); addApplication("dpkg", archGrid1, 4, packers_tab, PAGE_PACKERS); addApplication("gzip", archGrid1, 5, packers_tab, PAGE_PACKERS); addApplication("lha", archGrid1, 6, packers_tab, PAGE_PACKERS); addApplication("lzma", archGrid1, 7, packers_tab, PAGE_PACKERS); addApplication("rar", archGrid1, 8, packers_tab, PAGE_PACKERS); addApplication("tar", archGrid1, 9, packers_tab, PAGE_PACKERS); addApplication("unace", archGrid1, 10, packers_tab, PAGE_PACKERS); addApplication("unarj", archGrid1, 11, packers_tab, PAGE_PACKERS); addApplication("unrar", archGrid1, 12, packers_tab, PAGE_PACKERS); addApplication("unzip", archGrid1, 13, packers_tab, PAGE_PACKERS); addApplication("zip", archGrid1, 14, packers_tab, PAGE_PACKERS); addApplication("xz", archGrid1, 15, packers_tab, PAGE_PACKERS); // ---------------------------- CHECKSUM TAB ------------------------------------- QWidget *checksum_tab = new QWidget(tabWidget); QScrollArea* checksum_scroll = new QScrollArea(tabWidget); checksum_scroll->setFrameStyle(QFrame::NoFrame); checksum_scroll->setWidget(checksum_tab); // this also sets scrollacrea as the new parent for widget checksum_scroll->setWidgetResizable(true); // let the widget use every space available tabWidget->addTab(checksum_scroll, i18n("Checksum Utilities")); QGridLayout *archGrid2 = new QGridLayout(checksum_tab); archGrid2->setSpacing(6); archGrid2->setContentsMargins(11, 11, 11, 11); archGrid2->setAlignment(Qt::AlignTop); addApplication("md5sum", archGrid2, 0, checksum_tab, PAGE_CHECKSUM); addApplication("sha1sum", archGrid2, 1, checksum_tab, PAGE_CHECKSUM); addApplication("sha224sum", archGrid2, 2, checksum_tab, PAGE_CHECKSUM); addApplication("sha256sum", archGrid2, 3, checksum_tab, PAGE_CHECKSUM); addApplication("sha384sum", archGrid2, 4, checksum_tab, PAGE_CHECKSUM); addApplication("sha512sum", archGrid2, 5, checksum_tab, PAGE_CHECKSUM); kgDependenciesLayout->addWidget(tabWidget, 0, 0); } void KgDependencies::addApplication(QString name, QGridLayout *grid, int row, QWidget *parent, int page, QString additionalList) { // try to autodetect the full path name QString defaultValue = KrServices::fullPathName(name); if (defaultValue.isEmpty()) { QStringList list = additionalList.split(',', QString::SkipEmptyParts); for (int i = 0; i != list.count(); i++) if (!KrServices::fullPathName(list[ i ]).isEmpty()) { defaultValue = KrServices::fullPathName(list[ i ]); break; } } addLabel(grid, row, 0, name, parent); KonfiguratorURLRequester *fullPath = createURLRequester("Dependencies", name, defaultValue, parent, false, page); connect(fullPath->extension(), SIGNAL(applyManually(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); grid->addWidget(fullPath, row, 1); } void KgDependencies::slotApply(QObject *obj, QString configGroup, QString name) { KonfiguratorURLRequester *urlRequester = (KonfiguratorURLRequester *) obj; KConfigGroup group(krConfig, configGroup); group.writeEntry(name, urlRequester->url().toDisplayString(QUrl::PreferLocalFile)); QString usedPath = KrServices::fullPathName(name); if (urlRequester->url().toDisplayString(QUrl::PreferLocalFile) != usedPath) { group.writeEntry(name, usedPath); if (usedPath.isEmpty()) KMessageBox::error(this, i18n("The %1 path is incorrect, no valid path found.", urlRequester->url().toDisplayString(QUrl::PreferLocalFile))); else KMessageBox::error( this, i18n("The %1 path is incorrect, %2 used instead.", urlRequester->url().toDisplayString(QUrl::PreferLocalFile), usedPath)); urlRequester->setUrl(QUrl::fromLocalFile(usedPath)); } } int KgDependencies::activeSubPage() { return tabWidget->currentIndex(); } diff --git a/krusader/Konfigurator/kgdependencies.h b/krusader/Konfigurator/kgdependencies.h index 08e4e3d3..7768ef2f 100644 --- a/krusader/Konfigurator/kgdependencies.h +++ b/krusader/Konfigurator/kgdependencies.h @@ -1,61 +1,51 @@ -/*************************************************************************** - kgdependencies.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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 = 0); virtual int activeSubPage() Q_DECL_OVERRIDE; private: void addApplication(QString name, QGridLayout *grid, int row, QWidget *parent, int page, QString additionalList = QString()); public slots: void slotApply(QObject *obj, QString configGroup, QString name); private: QTabWidget *tabWidget; }; #endif /* __KGDEPENDENCIES_H__ */ diff --git a/krusader/Konfigurator/kggeneral.cpp b/krusader/Konfigurator/kggeneral.cpp index d3ddd5ec..0efb85be 100644 --- a/krusader/Konfigurator/kggeneral.cpp +++ b/krusader/Konfigurator/kggeneral.cpp @@ -1,341 +1,331 @@ -/*************************************************************************** - kggeneral.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kggeneral.h" // QtCore #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include #include "krresulttabledialog.h" #include "../defaults.h" #include "../kicons.h" #include "../krglobal.h" #define PAGE_GENERAL 0 #define PAGE_VIEWER 1 #define PAGE_EXTENSIONS 2 KgGeneral::KgGeneral(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { if (first) slotFindTools(); tabWidget = new QTabWidget(this); setWidget(tabWidget); setWidgetResizable(true); createGeneralTab(); createViewerTab(); createExtensionsTab(); } QWidget* KgGeneral::createTab(QString name) { QScrollArea *scrollArea = new QScrollArea(tabWidget); tabWidget->addTab(scrollArea, name); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidgetResizable(true); QWidget *tab = new QWidget(scrollArea); scrollArea->setWidget(tab); return tab; } void KgGeneral::createViewerTab() { QWidget *tab = createTab(i18n("Viewer/Editor")); QGridLayout *tabLayout = new QGridLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); tabLayout->addWidget(createCheckBox("General", "View In Separate Window", _ViewInSeparateWindow, i18n("Internal editor and viewer opens each file in a separate window"), tab, false, i18n("If checked, each file will open in a separate window, otherwise, the viewer will work in a single, tabbed mode"), PAGE_VIEWER)); // ------------------------- viewer ---------------------------------- QGroupBox *viewerGrp = createFrame(i18n("Viewer"), tab); tabLayout->addWidget(viewerGrp, 1, 0); QGridLayout *viewerGrid = createGridLayout(viewerGrp); QWidget * hboxWidget2 = new QWidget(viewerGrp); QHBoxLayout * hbox2 = new QHBoxLayout(hboxWidget2); QWidget * vboxWidget = new QWidget(hboxWidget2); QVBoxLayout * vbox = new QVBoxLayout(vboxWidget); vbox->addWidget(new QLabel(i18n("Default viewer mode:"), vboxWidget)); KONFIGURATOR_NAME_VALUE_TIP viewMode[] = // name value tooltip {{ i18n("Generic mode"), "generic", i18n("Use the system's default viewer") }, { i18n("Text mode"), "text", i18n("View the file in text-only mode") }, { i18n("Hex mode"), "hex", i18n("View the file in hex-mode (better for binary files)") }, { i18n("Lister mode"), "lister", i18n("View the file with lister (for huge text files)") } }; vbox->addWidget(createRadioButtonGroup("General", "Default Viewer Mode", "generic", 0, 4, viewMode, 4, vboxWidget, false, PAGE_VIEWER)); vbox->addWidget( createCheckBox("General", "UseOktetaViewer", _UseOktetaViewer, i18n("Use Okteta as Hex viewer"), vboxWidget, false, i18n("If available, use Okteta as Hex viewer instead of the internal viewer"), PAGE_VIEWER) ); QWidget * hboxWidget4 = new QWidget(vboxWidget); QHBoxLayout * hbox4 = new QHBoxLayout(hboxWidget4); QLabel *label5 = new QLabel(i18n("Use lister if the text file is bigger than:"), hboxWidget4); hbox4->addWidget(label5); KonfiguratorSpinBox *spinBox = createSpinBox("General", "Lister Limit", _ListerLimit, 0, 0x7FFFFFFF, hboxWidget4, false, PAGE_VIEWER); hbox4->addWidget(spinBox); QLabel *label6 = new QLabel(i18n("MB"), hboxWidget4); hbox4->addWidget(label6); vbox->addWidget(hboxWidget4); hbox2->addWidget(vboxWidget); viewerGrid->addWidget(hboxWidget2, 0, 0); // ------------------------- editor ---------------------------------- QGroupBox *editorGrp = createFrame(i18n("Editor"), tab); tabLayout->addWidget(editorGrp, 2, 0); QGridLayout *editorGrid = createGridLayout(editorGrp); QLabel *label1 = new QLabel(i18n("Editor:"), editorGrp); editorGrid->addWidget(label1, 0, 0); KonfiguratorURLRequester *urlReq = createURLRequester("General", "Editor", "internal editor", editorGrp, false, PAGE_VIEWER, false); editorGrid->addWidget(urlReq, 0, 1); QLabel *label2 = new QLabel(i18n("Hint: use 'internal editor' if you want to use Krusader's fast built-in editor"), editorGrp); editorGrid->addWidget(label2, 1, 0, 1, 2); } void KgGeneral::createExtensionsTab() { // ------------------------- atomic extensions ---------------------------------- QWidget *tab = createTab(i18n("Atomic extensions")); QGridLayout *tabLayout = new QGridLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); QWidget * vboxWidget2 = new QWidget(tab); tabLayout->addWidget(vboxWidget2); QVBoxLayout * vbox2 = new QVBoxLayout(vboxWidget2); QWidget * hboxWidget3 = new QWidget(vboxWidget2); vbox2->addWidget(hboxWidget3); QHBoxLayout * hbox3 = new QHBoxLayout(hboxWidget3); QLabel * atomLabel = new QLabel(i18n("Atomic extensions:"), hboxWidget3); hbox3->addWidget(atomLabel); int size = QFontMetrics(atomLabel->font()).height(); QToolButton *addButton = new QToolButton(hboxWidget3); hbox3->addWidget(addButton); QPixmap icon = krLoader->loadIcon("list-add", KIconLoader::Desktop, size); addButton->setFixedSize(icon.width() + 4, icon.height() + 4); addButton->setIcon(QIcon(icon)); connect(addButton, SIGNAL(clicked()), this, SLOT(slotAddExtension())); QToolButton *removeButton = new QToolButton(hboxWidget3); hbox3->addWidget(removeButton); icon = krLoader->loadIcon("list-remove", KIconLoader::Desktop, size); removeButton->setFixedSize(icon.width() + 4, icon.height() + 4); removeButton->setIcon(QIcon(icon)); connect(removeButton, SIGNAL(clicked()), this, SLOT(slotRemoveExtension())); QStringList defaultAtomicExtensions; defaultAtomicExtensions += ".tar.gz"; defaultAtomicExtensions += ".tar.bz2"; defaultAtomicExtensions += ".tar.lzma"; defaultAtomicExtensions += ".tar.xz"; defaultAtomicExtensions += ".moc.cpp"; listBox = createListBox("Look&Feel", "Atomic Extensions", defaultAtomicExtensions, vboxWidget2, true, PAGE_EXTENSIONS); vbox2->addWidget(listBox); } void KgGeneral::createGeneralTab() { QWidget *tab = createTab(i18n("General")); QGridLayout *kgGeneralLayout = new QGridLayout(tab); kgGeneralLayout->setSpacing(6); kgGeneralLayout->setContentsMargins(11, 11, 11, 11); // -------------------------- GENERAL GROUPBOX ---------------------------------- QGroupBox *generalGrp = createFrame(i18n("General"), tab); QGridLayout *generalGrid = createGridLayout(generalGrp); KONFIGURATOR_CHECKBOX_PARAM settings[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Warn On Exit", _WarnOnExit, i18n("Warn on exit"), false, i18n("Display a warning when trying to close the main window.") }, // KDE4: move warn on exit to the other confirmations {"Look&Feel", "Minimize To Tray", _ShowTrayIcon, i18n("Show and close to tray"), false, i18n("Show an icon in the system tray and keep running in the background when the window is closed.") }, }; KonfiguratorCheckBoxGroup *cbs = createCheckBoxGroup(2, 0, settings, 2 /*count*/, generalGrp, PAGE_GENERAL); generalGrid->addWidget(cbs, 0, 0); // temp dir QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Temp Folder:"), generalGrp)); KonfiguratorURLRequester *urlReq3 = createURLRequester("General", "Temp Directory", _TempDirectory, generalGrp, false, PAGE_GENERAL); urlReq3->setMode(KFile::Directory); connect(urlReq3->extension(), SIGNAL(applyManually(QObject*,QString,QString)), this, SLOT(applyTempDir(QObject*,QString,QString))); hbox->addWidget(urlReq3); generalGrid->addLayout(hbox, 13, 0, 1, 1); QLabel *label4 = new QLabel(i18n("Note: you must have full permissions for the temporary folder."), generalGrp); generalGrid->addWidget(label4, 14, 0, 1, 1); kgGeneralLayout->addWidget(generalGrp, 0 , 0); // ----------------------- delete mode -------------------------------------- QGroupBox *delGrp = createFrame(i18n("Delete mode"), tab); QGridLayout *delGrid = createGridLayout(delGrp); KONFIGURATOR_NAME_VALUE_TIP deleteMode[] = // name value tooltip {{i18n("Move to trash"), "true", i18n("Files will be moved to trash when deleted.")}, {i18n("Delete files"), "false", i18n("Files will be permanently deleted.")} }; KonfiguratorRadioButtons *trashRadio = createRadioButtonGroup("General", "Move To Trash", _MoveToTrash ? "true" : "false", 2, 0, deleteMode, 2, delGrp, false, PAGE_GENERAL); delGrid->addWidget(trashRadio); kgGeneralLayout->addWidget(delGrp, 1 , 0); // ----------------------- terminal ----------------------------------------- QGroupBox *terminalGrp = createFrame(i18n("Terminal"), tab); QGridLayout *terminalGrid = createGridLayout(terminalGrp); QLabel *label3 = new QLabel(i18n("External Terminal:"), generalGrp); terminalGrid->addWidget(label3, 0, 0); KonfiguratorURLRequester *urlReq2 = createURLRequester("General", "Terminal", _Terminal, generalGrp, false, PAGE_GENERAL, false); terminalGrid->addWidget(urlReq2, 0, 1); QLabel *terminalLabel = new QLabel(i18n("%d will be replaced by the workdir."), terminalGrp); terminalGrid->addWidget(terminalLabel, 1, 1); KONFIGURATOR_CHECKBOX_PARAM terminal_settings[] = { // cfg_class cfg_name default text restart tooltip {"General", "Send CDs", _SendCDs, i18n("Embedded Terminal sends Chdir on panel change"), false, i18n("When checked, whenever the panel is changed (for example, by pressing Tab), Krusader changes the current folder in the embedded terminal.") }, }; cbs = createCheckBoxGroup(1, 0, terminal_settings, 1 /*count*/, terminalGrp, PAGE_GENERAL); terminalGrid->addWidget(cbs, 2, 0, 1, 2); kgGeneralLayout->addWidget(terminalGrp, 2 , 0); } void KgGeneral::applyTempDir(QObject *obj, QString configGroup, QString name) { KonfiguratorURLRequester *urlReq = (KonfiguratorURLRequester *)obj; QString value = urlReq->url().toDisplayString(QUrl::PreferLocalFile); KConfigGroup(krConfig, configGroup).writeEntry(name, value); } void KgGeneral::slotFindTools() { QPointer dlg = new KrResultTableDialog(this, KrResultTableDialog::Tool, i18n("Search results"), i18n("Searching for tools..."), "tools-wizard", i18n("Make sure to install new tools in your $PATH (e.g. /usr/bin)")); dlg->exec(); delete dlg; } void KgGeneral::slotAddExtension() { bool ok; QString atomExt = QInputDialog::getText(this, i18n("Add new atomic extension"), i18n("Extension:"), QLineEdit::Normal, QString(), &ok); if (ok) { if (!atomExt.startsWith('.') || atomExt.indexOf('.', 1) == -1) KMessageBox::error(krMainWindow, i18n("Atomic extensions must start with '.' and must contain at least one more '.' character."), i18n("Error")); else listBox->addItem(atomExt); } } void KgGeneral::slotRemoveExtension() { QList list = listBox->selectedItems(); for (int i = 0; i != list.count(); i++) listBox->removeItem(list[ i ]->text()); } diff --git a/krusader/Konfigurator/kggeneral.h b/krusader/Konfigurator/kggeneral.h index 812290c4..674c05b9 100644 --- a/krusader/Konfigurator/kggeneral.h +++ b/krusader/Konfigurator/kggeneral.h @@ -1,60 +1,50 @@ -/*************************************************************************** - kgadvanced.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KGGENERAL_H #define KGGENERAL_H #include "konfiguratorpage.h" class KgGeneral : public KonfiguratorPage { Q_OBJECT public: explicit KgGeneral(bool first, QWidget* parent = 0); public slots: void applyTempDir(QObject *, QString, QString); void slotFindTools(); void slotAddExtension(); void slotRemoveExtension(); private: void createGeneralTab(); void createViewerTab(); void createExtensionsTab(); QWidget* createTab(QString name); QTabWidget *tabWidget; KonfiguratorListBox *listBox; }; #endif /* __KGGENERAL_H__ */ diff --git a/krusader/Konfigurator/kgpanel.cpp b/krusader/Konfigurator/kgpanel.cpp index 9274d367..e355f751 100644 --- a/krusader/Konfigurator/kgpanel.cpp +++ b/krusader/Konfigurator/kgpanel.cpp @@ -1,748 +1,737 @@ -/*************************************************************************** - kgpanel.cpp - description - ------------------- - copyright : (C) 2003 by Csaba Karai - copyright : (C) 2010 by Jan Lepper - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kgpanel.h" #include "../defaults.h" #include "../Dialogs/krdialogs.h" // QtGui #include // QtWidgets #include #include #include #include #include #include #include #include "../GUI/krtreewidget.h" #include "../Panel/krsearchbar.h" #include "../Panel/PanelView/krselectionmode.h" #include "../Panel/PanelView/krview.h" #include "../Panel/PanelView/krviewfactory.h" #include "../Panel/krlayoutfactory.h" enum { PAGE_GENERAL = 0, PAGE_VIEW, PAGE_PANELTOOLBAR, PAGE_MOUSE, PAGE_MEDIA_MENU, PAGE_LAYOUT }; KgPanel::KgPanel(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { tabWidget = new QTabWidget(this); setWidget(tabWidget); setWidgetResizable(true); setupGeneralTab(); setupPanelTab(); setupButtonsTab(); setupMouseModeTab(); setupMediaMenuTab(); setupLayoutTab(); } // --------------------------------------------------------------------------------------- // ---------------------------- General TAB ---------------------------------------------- // --------------------------------------------------------------------------------------- void KgPanel::setupGeneralTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("General")); QVBoxLayout *layout = new QVBoxLayout(tab); layout->setSpacing(6); layout->setContentsMargins(11, 11, 11, 11); // --------------------------------------------------------------------------------------- // ------------------------------- Navigator bar ------------------------------------- // --------------------------------------------------------------------------------------- QGroupBox *groupBox = createFrame(i18n("Navigator bar"), tab); QGridLayout *gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM navigatorbar_settings[] = { // cfg_class, cfg_name, default, text, restart, tooltip {"Look&Feel", "Navigator Edit Mode", false, i18n("Edit Mode by default"), true, i18n("Show editable path in Navigator bar by default") }, {"Look&Feel", "Navigator Full Path", false, i18n("Show full path by default"), true, i18n("Always show full path in Navigator bar by default.") }, }; cbs = createCheckBoxGroup(2, 0, navigatorbar_settings, 2 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(cbs, 0, 0); layout->addWidget(groupBox); // --------------------------------------------------------------------------------------- // ------------------------------- Operation --------------------------------------------- // --------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Operation"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM operation_settings[] = { // cfg_class, cfg_name, default, text, restart, tooltip {"Look&Feel", "Mark Dirs", _MarkDirs, i18n("Autoselect folders"), false, i18n("When matching the select criteria, not only files will be selected, but also folders.") }, {"Look&Feel", "Rename Selects Extension", true, i18n("Rename selects extension"), false, i18n("When renaming a file, the whole text is selected. If you want Total-Commander like renaming of just the name, without extension, uncheck this option.") }, {"Look&Feel", "UnselectBeforeOperation", _UnselectBeforeOperation, i18n("Unselect files before copy/move"), false, i18n("Unselect files, which are to be copied/moved, before the operation starts.") }, {"Look&Feel", "FilterDialogRemembersSettings", _FilterDialogRemembersSettings, i18n("Filter dialog remembers settings"), false, i18n("The filter dialog is opened with the last filter settings that where applied to the panel.") }, }; cbs = createCheckBoxGroup(2, 0, operation_settings, 4 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(cbs, 0, 0); layout->addWidget(groupBox); // --------------------------------------------------------------------------------------- // ------------------------------ Tabs --------------------------------------------------- // --------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Tabs"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM tabbar_settings[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Fullpath Tab Names", _FullPathTabNames, i18n("Use full path tab names"), true , i18n("Display the full path in the folder tabs. By default only the last part of the path is displayed.") }, {"Look&Feel", "Show Tab Buttons", true, i18n("Show new/close tab buttons"), true , i18n("Show the new/close tab buttons.") }, }; KonfiguratorCheckBoxGroup *cbs = createCheckBoxGroup(2, 0, tabbar_settings, 2 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(cbs, 0, 0, 1, 2); // ----------------- Tab Bar position ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Tab Bar position:"), groupBox)); KONFIGURATOR_NAME_VALUE_PAIR positions[] = { { i18n("Top"), "top" }, { i18n("Bottom"), "bottom" } }; KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Tab Bar Position", "bottom", positions, 2, groupBox, true, false, PAGE_GENERAL); hbox->addWidget(cmb); gridLayout->addLayout(hbox, 1, 0, Qt::AlignLeft); // ----------------- Show Tab bar ---------------------------------- KonfiguratorCheckBox *checkBox = createCheckBox("Look&Feel", "Show Tab Bar On Single Tab", true, i18n("Show Tab Bar on single tab"), groupBox, true, i18n("Show the tab bar with only one tab.")); gridLayout->addWidget(checkBox, 1, 1, Qt::AlignLeft); layout->addWidget(groupBox); // --------------------------------------------------------------------------------------- // ----------------------------- Search bar -------------------------------------------- // --------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Search bar"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM quicksearch[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "New Style Quicksearch", _NewStyleQuicksearch, i18n("Start by typing"), false, i18n("Open search bar and start searching by typing in panel.") }, {"Look&Feel", "Case Sensitive Quicksearch", _CaseSensitiveQuicksearch, i18n("Case sensitive"), false, i18n("Search must match case.") }, {"Look&Feel", "Up/Down Cancels Quicksearch", false, i18n("Up/Down cancels search"), false, i18n("Pressing the Up/Down buttons closes the search bar (only in search mode).") }, {"Look&Feel", "Navigation with Right Arrow Quicksearch", _NavigationWithRightArrowQuicksearch, i18n("Directory navigation with Right Arrow"), false, i18n("Pressing the Right button enters directory if no search text editing intention is captured.") }, }; quicksearchCheckboxes = createCheckBoxGroup(2, 0, quicksearch, 4 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(quicksearchCheckboxes, 0, 0, 1, -1); connect(quicksearchCheckboxes->find("New Style Quicksearch"), SIGNAL(stateChanged(int)), this, SLOT(slotDisable())); slotDisable(); // -------------- Search bar position ----------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Position:"), groupBox)); cmb = createComboBox("Look&Feel", "Quicksearch Position", "bottom", positions, 2, groupBox, true, false, PAGE_GENERAL); hbox->addWidget(cmb); hbox->addWidget(createSpacer(groupBox)); gridLayout->addLayout(hbox, 1, 0); layout->addWidget(groupBox); // -------------- Default search mode ----------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default mode:"), groupBox)); KONFIGURATOR_NAME_VALUE_PAIR modes[] = { { i18n("Search"), QString::number(KrSearchBar::MODE_SEARCH) }, { i18n("Select"), QString::number(KrSearchBar::MODE_SELECT) }, { i18n("Filter"), QString::number(KrSearchBar::MODE_FILTER) } }; cmb = createComboBox("Look&Feel", "Default Search Mode", QString::number(KrSearchBar::MODE_SEARCH), modes, 3, groupBox, true, false, PAGE_GENERAL); cmb->setToolTip(i18n("Set the default mode on first usage")); hbox->addWidget(cmb); hbox->addWidget(createSpacer(groupBox)); gridLayout->addLayout(hbox, 1, 1); layout->addWidget(groupBox); // -------------------------------------------------------------------------------------------- // ------------------------------- Status/Totalsbar settings ---------------------------------- // -------------------------------------------------------------------------------------------- groupBox = createFrame(i18n("Status/Totalsbar"), tab); gridLayout = createGridLayout(groupBox); KONFIGURATOR_CHECKBOX_PARAM barSettings[] = { {"Look&Feel", "Show Size In Bytes", false, i18n("Show size in bytes too"), true, i18n("Show size in bytes too") }, {"Look&Feel", "ShowSpaceInformation", true, i18n("Show space information"), true, i18n("Show free/total space on the device") }, }; KonfiguratorCheckBoxGroup *barSett = createCheckBoxGroup(2, 0, barSettings, 2 /*count*/, groupBox, PAGE_GENERAL); gridLayout->addWidget(barSett, 1, 0, 1, 2); layout->addWidget(groupBox); } // -------------------------------------------------------------------------------------------- // ------------------------------------ Layout Tab -------------------------------------------- // -------------------------------------------------------------------------------------------- void KgPanel::setupLayoutTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Layout")); QGridLayout *grid = createGridLayout(tab); QStringList layoutNames = KrLayoutFactory::layoutNames(); int numLayouts = layoutNames.count(); grid->addWidget(createSpacer(tab), 0, 2); QLabel *l = new QLabel(i18n("Layout:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 0, 0); KONFIGURATOR_NAME_VALUE_PAIR *layouts = new KONFIGURATOR_NAME_VALUE_PAIR[numLayouts]; for (int i = 0; i != numLayouts; i++) { layouts[ i ].text = KrLayoutFactory::layoutDescription(layoutNames[i]); layouts[ i ].value = layoutNames[i]; } KonfiguratorComboBox *cmb = createComboBox("PanelLayout", "Layout", "default", layouts, numLayouts, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 0, 1); delete [] layouts; l = new QLabel(i18n("Frame Color:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 1, 0); KONFIGURATOR_NAME_VALUE_PAIR frameColor[] = { { i18nc("Frame color", "Defined by Layout"), "default" }, { i18nc("Frame color", "None"), "none" }, { i18nc("Frame color", "Statusbar"), "Statusbar" } }; cmb = createComboBox("PanelLayout", "FrameColor", "default", frameColor, 3, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 1, 1); l = new QLabel(i18n("Frame Shape:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 2, 0); KONFIGURATOR_NAME_VALUE_PAIR frameShape[] = { { i18nc("Frame shape", "Defined by Layout"), "default" }, { i18nc("Frame shape", "None"), "NoFrame" }, { i18nc("Frame shape", "Box"), "Box" }, { i18nc("Frame shape", "Panel"), "Panel" }, }; cmb = createComboBox("PanelLayout", "FrameShape", "default", frameShape, 4, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 2, 1); l = new QLabel(i18n("Frame Shadow:"), tab); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); grid->addWidget(l, 3, 0); KONFIGURATOR_NAME_VALUE_PAIR frameShadow[] = { { i18nc("Frame shadow", "Defined by Layout"), "default" }, { i18nc("Frame shadow", "None"), "Plain" }, { i18nc("Frame shadow", "Raised"), "Raised" }, { i18nc("Frame shadow", "Sunken"), "Sunken" }, }; cmb = createComboBox("PanelLayout", "FrameShadow", "default", frameShadow, 4, tab, true, false, PAGE_LAYOUT); grid->addWidget(cmb, 3, 1); } void KgPanel::setupView(KrViewInstance *instance, QWidget *parent) { QGridLayout *grid = createGridLayout(parent); // -------------------- Filelist icon size ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default icon size:"), parent)); KONFIGURATOR_NAME_VALUE_PAIR *iconSizes = new KONFIGURATOR_NAME_VALUE_PAIR[KrView::iconSizes.count()]; for(int i = 0; i < KrView::iconSizes.count(); i++) iconSizes[i].text = iconSizes[i].value = QString::number(KrView::iconSizes[i]); KonfiguratorComboBox *cmb = createComboBox(instance->name(), "IconSize", _FilelistIconSize, iconSizes, KrView::iconSizes.count(), parent, true, true, PAGE_VIEW); delete [] iconSizes; cmb->lineEdit()->setValidator(new QRegExpValidator(QRegExp("[1-9]\\d{0,1}"), cmb)); hbox->addWidget(cmb); hbox->addWidget(createSpacer(parent)); grid->addLayout(hbox, 1, 0); //-------------------------------------------------------------------- KONFIGURATOR_CHECKBOX_PARAM iconSettings[] = // cfg_class cfg_name default text restart tooltip { {instance->name(), "With Icons", _WithIcons, i18n("Use icons in the filenames"), true, i18n("Show the icons for filenames and folders.") }, {instance->name(), "ShowPreviews", false, i18n("Show previews by default"), false, i18n("Show previews of files and folders.") }, }; KonfiguratorCheckBoxGroup *iconSett = createCheckBoxGroup(2, 0, iconSettings, 2 /*count*/, parent, PAGE_VIEW); grid->addWidget(iconSett, 2, 0, 1, 2); } // ---------------------------------------------------------------------------------- // ---------------------------- VIEW TAB ------------------------------------------- // ---------------------------------------------------------------------------------- void KgPanel::setupPanelTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab_panel = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab_panel); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("View")); QGridLayout *panelLayout = new QGridLayout(tab_panel); panelLayout->setSpacing(6); panelLayout->setContentsMargins(11, 11, 11, 11); QGroupBox *panelGrp = createFrame(i18n("General"), tab_panel); panelLayout->addWidget(panelGrp, 0, 0); QGridLayout *panelGrid = createGridLayout(panelGrp); // ---------------------------------------------------------------------------------- // ---------------------------- General settings ----------------------------------- // ---------------------------------------------------------------------------------- // -------------------- Panel Font ---------------------------------- QHBoxLayout *hbox = new QHBoxLayout(); QHBoxLayout *fontLayout = new QHBoxLayout(); fontLayout->addWidget(new QLabel(i18n("View font:"), panelGrp)); KonfiguratorFontChooser *chsr = createFontChooser("Look&Feel", "Filelist Font", _FilelistFont, panelGrp, true, PAGE_VIEW); fontLayout->addWidget(chsr); fontLayout->addStretch(1); hbox->addLayout(fontLayout, 1); // -------------------- Panel Tooltip ---------------------------------- QHBoxLayout *tooltipLayout = new QHBoxLayout(); QLabel *tooltipLabel = new QLabel(i18n("Tooltip delay (msec):")); tooltipLabel->setWhatsThis(i18n("The duration after a tooltip is shown for a file item, in " "milliseconds. Set a negative value to disable tooltips.")); tooltipLayout->addWidget(tooltipLabel); KonfiguratorSpinBox *tooltipSpinBox = createSpinBox("Look&Feel", "Panel Tooltip Delay", 1000, -100, 5000, panelGrp, false, PAGE_VIEW); tooltipSpinBox->setSingleStep(100); tooltipLayout->addWidget(tooltipSpinBox); tooltipLayout->addStretch(1); hbox->addLayout(tooltipLayout, 1); panelGrid->addLayout(hbox, 1, 0); // -------------------- General options ---------------------------------- KONFIGURATOR_CHECKBOX_PARAM panelSettings[] = // cfg_class cfg_name default text restart tooltip { {"Look&Feel", "Human Readable Size", _HumanReadableSize, i18n("Use human-readable file size"), true , i18n("File sizes are displayed in B, KB, MB and GB, not just in bytes.") }, {"Look&Feel", "Show Hidden", _ShowHidden, i18n("Show hidden files"), false, i18n("Display files beginning with a dot.") }, {"Look&Feel", "Numeric permissions", _NumericPermissions, i18n("Numeric Permissions"), true, i18n("Show octal numbers (0755) instead of the standard permissions (rwxr-xr-x) in the permission column.") }, {"Look&Feel", "Load User Defined Folder Icons", _UserDefinedFolderIcons, i18n("Load the user defined folder icons"), true , i18n("Load the user defined folder icons (can cause decrease in performance).") }, {"Look&Feel", "Always Show Current Item", _AlwaysShowCurrentItem, i18n("Always show current item"), false, i18n("Show current item border decoration in inactive panel.") }, }; KonfiguratorCheckBoxGroup *panelSett = createCheckBoxGroup(2, 0, panelSettings, 5 /*count*/, panelGrp, PAGE_VIEW); panelGrid->addWidget(panelSett, 3, 0, 1, 2); // ========================================================= panelGrid->addWidget(createLine(panelGrp), 4, 0); // ------------------------ Sort Method ---------------------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Sort method:"), panelGrp)); KONFIGURATOR_NAME_VALUE_PAIR sortMethods[] = {{ i18n("Alphabetical"), QString::number(KrViewProperties::Alphabetical) }, { i18n("Alphabetical and numbers"), QString::number(KrViewProperties::AlphabeticalNumbers) }, { i18n("Character code"), QString::number(KrViewProperties::CharacterCode) }, { i18n("Character code and numbers"), QString::number(KrViewProperties::CharacterCodeNumbers) }, { i18nc("Krusader sort", "Krusader"), QString::number(KrViewProperties::Krusader) } }; KonfiguratorComboBox *cmb = createComboBox("Look&Feel", "Sort method", QString::number(_DefaultSortMethod), sortMethods, 5, panelGrp, true, false, PAGE_VIEW); hbox->addWidget(cmb); hbox->addWidget(createSpacer(panelGrp)); panelGrid->addLayout(hbox, 5, 0); // ------------------------ Sort Options ---------------------------------- KONFIGURATOR_CHECKBOX_PARAM sortSettings[] = // cfg_class, cfg_name, default, text, restart, tooltip { {"Look&Feel", "Case Sensative Sort", _CaseSensativeSort, i18n("Case sensitive sorting"), true, i18n("All files beginning with capital letters appear before files beginning with non-capital letters (UNIX default).") }, {"Look&Feel", "Show Directories First", true, i18n("Show folders first"), true, 0 }, {"Look&Feel", "Always sort dirs by name", false, i18n("Always sort dirs by name"), true, i18n("Folders are sorted by name, regardless of the sort column.") }, {"Look&Feel", "Locale Aware Sort", true, i18n("Locale aware sorting"), true, i18n("The sorting is performed in a locale- and also platform-dependent manner. Can be slow.") }, }; KonfiguratorCheckBoxGroup *sortSett = createCheckBoxGroup(2, 0, sortSettings, 4 /*count*/, panelGrp, PAGE_VIEW); sortSett->find("Show Directories First")->addDep(sortSett->find("Always sort dirs by name")); panelGrid->addWidget(sortSett, 6, 0, 1, 2); // ---------------------------------------------------------------------------------- // ---------------------------- View modes ----------------------------------------- // ---------------------------------------------------------------------------------- panelGrp = createFrame(i18n("View modes"), tab_panel); panelLayout->addWidget(panelGrp, 1, 0); panelGrid = createGridLayout(panelGrp); // -------------------- Default Panel Type ---------------------------------- hbox = new QHBoxLayout(); hbox->addWidget(new QLabel(i18n("Default view mode:"), panelGrp)); QList views = KrViewFactory::registeredViews(); const int viewsSize = views.size(); KONFIGURATOR_NAME_VALUE_PAIR *panelTypes = new KONFIGURATOR_NAME_VALUE_PAIR[ viewsSize ]; QString defType = QString('0'); for (int i = 0; i != viewsSize; i++) { KrViewInstance * inst = views[ i ]; panelTypes[ i ].text = inst->description(); panelTypes[ i ].text.remove('&'); panelTypes[ i ].value = QString("%1").arg(inst->id()); if (inst->id() == KrViewFactory::defaultViewId()) defType = QString("%1").arg(inst->id()); } cmb = createComboBox("Look&Feel", "Default Panel Type", defType, panelTypes, viewsSize, panelGrp, false, false, PAGE_VIEW); hbox->addWidget(cmb); hbox->addWidget(createSpacer(panelGrp)); delete [] panelTypes; panelGrid->addLayout(hbox, 0, 0); // ----- Individual Settings Per View Type ------------------------ QTabWidget *tabs_view = new QTabWidget(panelGrp); panelGrid->addWidget(tabs_view, 11, 0); for(int i = 0; i < views.count(); i++) { QWidget *tab = new QWidget(tabs_view); tabs_view->addTab(tab, views[i]->description()); setupView(views[i], tab); } } // ----------------------------------------------------------------------------------- // -------------------------- Panel Toolbar TAB ---------------------------------- // ----------------------------------------------------------------------------------- void KgPanel::setupButtonsTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Buttons")); QBoxLayout * tabLayout = new QVBoxLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); KONFIGURATOR_CHECKBOX_PARAM buttonsParams[] = // cfg_class cfg_name default text restart tooltip { {"ListPanelButtons", "Icons", false, i18n("Toolbar buttons have icons"), true, "" }, {"Look&Feel", "Media Button Visible", true, i18n("Show Media Button"), true , i18n("The media button will be visible.") }, {"Look&Feel", "Back Button Visible", false, i18n("Show Back Button"), true , "Goes back in history." }, {"Look&Feel", "Forward Button Visible", false, i18n("Show Forward Button"), true , "Goes forward in history." }, {"Look&Feel", "History Button Visible", true, i18n("Show History Button"), true , i18n("The history button will be visible.") }, {"Look&Feel", "Bookmarks Button Visible", true, i18n("Show Bookmarks Button"), true , i18n("The bookmarks button will be visible.") }, {"Look&Feel", "Panel Toolbar visible", _PanelToolBar, i18n("Show Panel Toolbar"), true, i18n("The panel toolbar will be visible.") }, }; buttonsCheckboxes = createCheckBoxGroup(1, 0, buttonsParams, 7/*count*/, tab, PAGE_PANELTOOLBAR); connect(buttonsCheckboxes->find("Panel Toolbar visible"), SIGNAL(stateChanged(int)), this, SLOT(slotEnablePanelToolbar())); tabLayout->addWidget(buttonsCheckboxes, 0, 0); QGroupBox * panelToolbarGrp = createFrame(i18n("Visible Panel Toolbar buttons"), tab); QGridLayout * panelToolbarGrid = createGridLayout(panelToolbarGrp); KONFIGURATOR_CHECKBOX_PARAM panelToolbarButtonsParams[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Equal Button Visible", _cdOther, i18n("Equal button (=)"), true , i18n("Changes the panel folder to the other panel folder.") }, {"Look&Feel", "Up Button Visible", _cdUp, i18n("Up button (..)"), true , i18n("Changes the panel folder to the parent folder.") }, {"Look&Feel", "Home Button Visible", _cdHome, i18n("Home button (~)"), true , i18n("Changes the panel folder to the home folder.") }, {"Look&Feel", "Root Button Visible", _cdRoot, i18n("Root button (/)"), true , i18n("Changes the panel folder to the root folder.") }, {"Look&Feel", "SyncBrowse Button Visible", _syncBrowseButton, i18n("Toggle-button for sync-browsing"), true , i18n("Each folder change in the panel is also performed in the other panel.") }, }; panelToolbarButtonsCheckboxes = createCheckBoxGroup(1, 0, panelToolbarButtonsParams, sizeof(panelToolbarButtonsParams) / sizeof(*panelToolbarButtonsParams), panelToolbarGrp, PAGE_PANELTOOLBAR); panelToolbarGrid->addWidget(panelToolbarButtonsCheckboxes, 0, 0); tabLayout->addWidget(panelToolbarGrp, 1, 0); // Enable panel toolbar checkboxes slotEnablePanelToolbar(); } // --------------------------------------------------------------------------- // -------------------------- Mouse TAB ---------------------------------- // --------------------------------------------------------------------------- void KgPanel::setupMouseModeTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab_mouse = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab_mouse); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Selection Mode")); QGridLayout *mouseLayout = new QGridLayout(tab_mouse); mouseLayout->setSpacing(6); mouseLayout->setContentsMargins(11, 11, 11, 11); // -------------- General ----------------- QGroupBox *mouseGeneralGroup = createFrame(i18n("General"), tab_mouse); QGridLayout *mouseGeneralGrid = createGridLayout(mouseGeneralGroup); mouseGeneralGrid->setSpacing(0); mouseGeneralGrid->setContentsMargins(5, 5, 5, 5); KONFIGURATOR_NAME_VALUE_TIP mouseSelection[] = { // name value tooltip { i18n("Krusader Mode"), "0", i18n("Both keys allow selecting files. To select more than one file, hold the Ctrl key and click the left mouse button. Right-click menu is invoked using a short click on the right mouse button.") }, { i18n("Konqueror Mode"), "1", i18n("Pressing the left mouse button selects files - you can click and select multiple files. Right-click menu is invoked using a short click on the right mouse button.") }, { i18n("Total-Commander Mode"), "2", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button selects multiple files and the right-click menu is invoked by pressing and holding the right mouse button.") }, { i18n("Ergonomic Mode"), "4", i18n("The left mouse button does not select, but sets the current file without affecting the current selection. The right mouse button invokes the context-menu. You can select with Ctrl key and the left button.") }, { i18n("Custom Selection Mode"), "3", i18n("Design your own selection mode.") } }; mouseRadio = createRadioButtonGroup("Look&Feel", "Mouse Selection", "0", 1, 5, mouseSelection, 5, mouseGeneralGroup, true, PAGE_MOUSE); mouseRadio->layout()->setContentsMargins(0, 0, 0, 0); mouseGeneralGrid->addWidget(mouseRadio, 0, 0); for (int i = 0; i != mouseRadio->count(); i++) connect(mouseRadio->find(i), SIGNAL(clicked()), SLOT(slotSelectionModeChanged())); mouseLayout->addWidget(mouseGeneralGroup, 0, 0); // -------------- Details ----------------- QGroupBox *mouseDetailGroup = createFrame(i18n("Details"), tab_mouse); QGridLayout *mouseDetailGrid = createGridLayout(mouseDetailGroup); mouseDetailGrid->setSpacing(0); mouseDetailGrid->setContentsMargins(5, 5, 5, 5); KONFIGURATOR_NAME_VALUE_TIP singleOrDoubleClick[] = { // name value tooltip { i18n("Double-click selects (classic)"), "0", i18n("A single click on a file will select and focus, a double click opens the file or steps into the folder.") }, { i18n("Obey global selection policy"), "1", i18n("

Use global setting:

Plasma System Settings -> Input Devices -> Mouse

") } }; KonfiguratorRadioButtons *clickRadio = createRadioButtonGroup("Look&Feel", "Single Click Selects", "0", 1, 0, singleOrDoubleClick, 2, mouseDetailGroup, true, PAGE_MOUSE); clickRadio->layout()->setContentsMargins(0, 0, 0, 0); mouseDetailGrid->addWidget(clickRadio, 0, 0); KONFIGURATOR_CHECKBOX_PARAM mouseCheckboxesParam[] = { // {cfg_class, cfg_name, default // text, restart, // tooltip } {"Custom Selection Mode", "QT Selection", _QtSelection, i18n("Based on KDE's selection mode"), true, i18n("If checked, use a mode based on KDE's style.") }, {"Custom Selection Mode", "Left Selects", _LeftSelects, i18n("Left mouse button selects"), true, i18n("If checked, left clicking an item will select it.") }, {"Custom Selection Mode", "Left Preserves", _LeftPreserves, i18n("Left mouse button preserves selection"), true, i18n("If checked, left clicking an item will select it, but will not unselect other, already selected items.") }, {"Custom Selection Mode", "ShiftCtrl Left Selects", _ShiftCtrlLeft, i18n("Shift/Ctrl-Left mouse button selects"), true, i18n("If checked, Shift/Ctrl left clicking will select items.\nNote: this is meaningless if 'Left Button Selects' is checked.") }, {"Custom Selection Mode", "Right Selects", _RightSelects, i18n("Right mouse button selects"), true, i18n("If checked, right clicking an item will select it.") }, {"Custom Selection Mode", "Right Preserves", _RightPreserves, i18n("Right mouse button preserves selection"), true, i18n("If checked, right clicking an item will select it, but will not unselect other, already selected items.") }, {"Custom Selection Mode", "ShiftCtrl Right Selects", _ShiftCtrlRight, i18n("Shift/Ctrl-Right mouse button selects"), true, i18n("If checked, Shift/Ctrl right clicking will select items.\nNote: this is meaningless if 'Right Button Selects' is checked.") }, {"Custom Selection Mode", "Space Moves Down", _SpaceMovesDown, i18n("Spacebar moves down"), true, i18n("If checked, pressing the spacebar will select the current item and move down.\nOtherwise, current item is selected, but remains the current item.") }, {"Custom Selection Mode", "Space Calc Space", _SpaceCalcSpace, i18n("Spacebar calculates disk space"), true, i18n("If checked, pressing the spacebar while the current item is a folder, will (except from selecting the folder)\ncalculate space occupied of the folder (recursively).") }, {"Custom Selection Mode", "Insert Moves Down", _InsertMovesDown, i18n("Insert moves down"), true, i18n("If checked, pressing Insert will select the current item, and move down to the next item.\nOtherwise, current item is not changed.") }, {"Custom Selection Mode", "Immediate Context Menu", _ImmediateContextMenu, i18n("Right clicking pops context menu immediately"), true, i18n("If checked, right clicking will result in an immediate showing of the context menu.\nOtherwise, user needs to click and hold the right mouse button for 500ms.") }, }; mouseCheckboxes = createCheckBoxGroup(1, 0, mouseCheckboxesParam, 11 /*count*/, mouseDetailGroup, PAGE_MOUSE); mouseDetailGrid->addWidget(mouseCheckboxes, 1, 0); for (int i = 0; i < mouseCheckboxes->count(); i++) connect(mouseCheckboxes->find(i), SIGNAL(clicked()), SLOT(slotMouseCheckBoxChanged())); mouseLayout->addWidget(mouseDetailGroup, 0, 1, 2, 1); // Disable the details-button if not in custom-mode slotSelectionModeChanged(); // -------------- Preview ----------------- QGroupBox *mousePreviewGroup = createFrame(i18n("Preview"), tab_mouse); QGridLayout *mousePreviewGrid = createGridLayout(mousePreviewGroup); // TODO preview mousePreview = new KrTreeWidget(mousePreviewGroup); mousePreviewGrid->addWidget(mousePreview, 0 , 0); mousePreviewGroup->setEnabled(false); // TODO re-enable once the preview is implemented // ------------------------------------------ mouseLayout->addWidget(mousePreviewGroup, 1, 0); } // --------------------------------------------------------------------------- // -------------------------- Media Menu TAB ---------------------------------- // --------------------------------------------------------------------------- void KgPanel::setupMediaMenuTab() { QScrollArea *scrollArea = new QScrollArea(tabWidget); QWidget *tab = new QWidget(scrollArea); scrollArea->setFrameStyle(QFrame::NoFrame); scrollArea->setWidget(tab); scrollArea->setWidgetResizable(true); tabWidget->addTab(scrollArea, i18n("Media Menu")); QBoxLayout * tabLayout = new QVBoxLayout(tab); tabLayout->setSpacing(6); tabLayout->setContentsMargins(11, 11, 11, 11); KONFIGURATOR_CHECKBOX_PARAM mediaMenuParams[] = { // cfg_class cfg_name default text restart tooltip {"MediaMenu", "ShowPath", true, i18n("Show Mount Path"), false, 0 }, {"MediaMenu", "ShowFSType", true, i18n("Show File System Type"), false, 0 }, }; KonfiguratorCheckBoxGroup *mediaMenuCheckBoxes = createCheckBoxGroup(1, 0, mediaMenuParams, sizeof(mediaMenuParams) / sizeof(*mediaMenuParams), tab, PAGE_MEDIA_MENU); tabLayout->addWidget(mediaMenuCheckBoxes, 0, 0); QHBoxLayout *showSizeHBox = new QHBoxLayout(); showSizeHBox->addWidget(new QLabel(i18n("Show Size:"), tab)); KONFIGURATOR_NAME_VALUE_PAIR showSizeValues[] = { { i18nc("setting 'show size'", "Always"), "Always" }, { i18nc("setting 'show size'", "When Device has no Label"), "WhenNoLabel" }, { i18nc("setting 'show size'", "Never"), "Never" }, }; KonfiguratorComboBox *showSizeCmb = createComboBox("MediaMenu", "ShowSize", "Always", showSizeValues, sizeof(showSizeValues) / sizeof(*showSizeValues), tab, false, false, PAGE_MEDIA_MENU); showSizeHBox->addWidget(showSizeCmb); showSizeHBox->addStretch(); tabLayout->addLayout(showSizeHBox); tabLayout->addStretch(); } void KgPanel::slotDisable() { bool isNewStyleQuickSearch = quicksearchCheckboxes->find("New Style Quicksearch")->isChecked(); quicksearchCheckboxes->find("Case Sensitive Quicksearch")->setEnabled(isNewStyleQuickSearch); } void KgPanel::slotEnablePanelToolbar() { bool enableTB = buttonsCheckboxes->find("Panel Toolbar visible")->isChecked(); panelToolbarButtonsCheckboxes->find("Root Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Home Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Up Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("Equal Button Visible")->setEnabled(enableTB); panelToolbarButtonsCheckboxes->find("SyncBrowse Button Visible")->setEnabled(enableTB); } void KgPanel::slotSelectionModeChanged() { KrSelectionMode *selectionMode = KrSelectionMode::getSelectionHandlerForMode(mouseRadio->selectedValue()); if (selectionMode == NULL) //User mode return; selectionMode->init(); mouseCheckboxes->find("QT Selection")->setChecked(selectionMode->useQTSelection()); mouseCheckboxes->find("Left Selects")->setChecked(selectionMode->leftButtonSelects()); mouseCheckboxes->find("Left Preserves")->setChecked(selectionMode->leftButtonPreservesSelection()); mouseCheckboxes->find("ShiftCtrl Left Selects")->setChecked(selectionMode->shiftCtrlLeftButtonSelects()); mouseCheckboxes->find("Right Selects")->setChecked(selectionMode->rightButtonSelects()); mouseCheckboxes->find("Right Preserves")->setChecked(selectionMode->rightButtonPreservesSelection()); mouseCheckboxes->find("ShiftCtrl Right Selects")->setChecked(selectionMode->shiftCtrlRightButtonSelects()); mouseCheckboxes->find("Space Moves Down")->setChecked(selectionMode->spaceMovesDown()); mouseCheckboxes->find("Space Calc Space")->setChecked(selectionMode->spaceCalculatesDiskSpace()); mouseCheckboxes->find("Insert Moves Down")->setChecked(selectionMode->insertMovesDown()); mouseCheckboxes->find("Immediate Context Menu")->setChecked(selectionMode->showContextMenu() == -1); } void KgPanel::slotMouseCheckBoxChanged() { mouseRadio->selectButton("3"); //custom selection mode } int KgPanel::activeSubPage() { return tabWidget->currentIndex(); } diff --git a/krusader/Konfigurator/kgpanel.h b/krusader/Konfigurator/kgpanel.h index 6e2b5496..a17dfc81 100644 --- a/krusader/Konfigurator/kgpanel.h +++ b/krusader/Konfigurator/kgpanel.h @@ -1,74 +1,64 @@ -/*************************************************************************** - kgpanel.h - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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 = 0); virtual int activeSubPage() Q_DECL_OVERRIDE; protected: KonfiguratorCheckBoxGroup *cbs; KonfiguratorCheckBoxGroup* quicksearchCheckboxes; KonfiguratorCheckBoxGroup *panelToolbarButtonsCheckboxes; KonfiguratorCheckBoxGroup *buttonsCheckboxes; KonfiguratorRadioButtons *mouseRadio; KonfiguratorCheckBoxGroup *mouseCheckboxes; KrTreeWidget* mousePreview; protected slots: void slotDisable(); 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.cpp b/krusader/Konfigurator/kgprotocols.cpp index 70af3a38..e3d42df9 100644 --- a/krusader/Konfigurator/kgprotocols.cpp +++ b/krusader/Konfigurator/kgprotocols.cpp @@ -1,398 +1,388 @@ -/*************************************************************************** - KgProtocols.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kgprotocols.h" #include "../krglobal.h" #include "../krservices.h" // QtCore #include #include // QtWidgets #include #include #include #include #include #include #include KgProtocols::KgProtocols(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { QGridLayout *KgProtocolsLayout = new QGridLayout(this); KgProtocolsLayout->setSpacing(6); // -------------------------- LINK VIEW ---------------------------------- QGroupBox *linkGrp = createFrame(i18n("Links"), this); QGridLayout *linkGrid = createGridLayout(linkGrp); QStringList labels; labels << i18n("Defined Links"); linkList = new KrTreeWidget(linkGrp); linkList->setHeaderLabels(labels); linkList->setRootIsDecorated(true); linkGrid->addWidget(linkList, 0, 0); KgProtocolsLayout->addWidget(linkGrp, 0, 0, 2, 1); // -------------------------- BUTTONS ---------------------------------- QWidget *vbox1Widget = new QWidget(this); QVBoxLayout *vbox1 = new QVBoxLayout(vbox1Widget); addSpacer(vbox1); btnAddProtocol = new QPushButton(vbox1Widget); btnAddProtocol->setIcon(krLoader->loadIcon("arrow-left", KIconLoader::Small)); btnAddProtocol->setWhatsThis(i18n("Add protocol to the link list.")); vbox1->addWidget(btnAddProtocol); btnRemoveProtocol = new QPushButton(vbox1Widget); btnRemoveProtocol->setIcon(krLoader->loadIcon("arrow-right", KIconLoader::Small)); btnRemoveProtocol->setWhatsThis(i18n("Remove protocol from the link list.")); vbox1->addWidget(btnRemoveProtocol); addSpacer(vbox1); KgProtocolsLayout->addWidget(vbox1Widget, 0 , 1); QWidget *vbox2Widget = new QWidget(this); QVBoxLayout *vbox2 = new QVBoxLayout(vbox2Widget); addSpacer(vbox2); btnAddMime = new QPushButton(vbox2Widget); btnAddMime->setIcon(krLoader->loadIcon("arrow-left", KIconLoader::Small)); btnAddMime->setWhatsThis(i18n("Add MIME to the selected protocol on the link list.")); vbox2->addWidget(btnAddMime); btnRemoveMime = new QPushButton(vbox2Widget); btnRemoveMime->setIcon(krLoader->loadIcon("arrow-right", KIconLoader::Small)); btnRemoveMime->setWhatsThis(i18n("Remove MIME from the link list.")); vbox2->addWidget(btnRemoveMime); addSpacer(vbox2); KgProtocolsLayout->addWidget(vbox2Widget, 1 , 1); // -------------------------- PROTOCOLS LISTBOX ---------------------------------- QGroupBox *protocolGrp = createFrame(i18n("Protocols"), this); QGridLayout *protocolGrid = createGridLayout(protocolGrp); protocolList = new KrListWidget(protocolGrp); loadProtocols(); protocolGrid->addWidget(protocolList, 0, 0); KgProtocolsLayout->addWidget(protocolGrp, 0 , 2); // -------------------------- MIMES LISTBOX ---------------------------------- QGroupBox *mimeGrp = createFrame(i18n("MIMEs"), this); QGridLayout *mimeGrid = createGridLayout(mimeGrp); mimeList = new KrListWidget(mimeGrp); loadMimes(); mimeGrid->addWidget(mimeList, 0, 0); KgProtocolsLayout->addWidget(mimeGrp, 1 , 2); // -------------------------- CONNECT TABLE ---------------------------------- connect(protocolList, SIGNAL(itemSelectionChanged()), this, SLOT(slotDisableButtons())); connect(linkList, SIGNAL(itemSelectionChanged()), this, SLOT(slotDisableButtons())); connect(mimeList, SIGNAL(itemSelectionChanged()), this, SLOT(slotDisableButtons())); connect(linkList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotDisableButtons())); connect(btnAddProtocol, SIGNAL(clicked()) , this, SLOT(slotAddProtocol())); connect(btnRemoveProtocol, SIGNAL(clicked()) , this, SLOT(slotRemoveProtocol())); connect(btnAddMime, SIGNAL(clicked()) , this, SLOT(slotAddMime())); connect(btnRemoveMime, SIGNAL(clicked()) , this, SLOT(slotRemoveMime())); loadInitialValues(); slotDisableButtons(); } void KgProtocols::addSpacer(QBoxLayout *layout) { layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); } void KgProtocols::loadProtocols() { QStringList protocols = KProtocolInfo::protocols(); protocols.sort(); foreach(const QString &protocol, protocols) { QUrl u; u.setScheme(protocol); if(KProtocolManager::inputType(u) == KProtocolInfo::T_FILESYSTEM) { protocolList->addItem(protocol); } } } void KgProtocols::loadMimes() { QMimeDatabase db; QList mimes = db.allMimeTypes(); for (QList::const_iterator it = mimes.constBegin(); it != mimes.constEnd(); ++it) mimeList->addItem((*it).name()); mimeList->sortItems(); } void KgProtocols::slotDisableButtons() { btnAddProtocol->setEnabled(protocolList->selectedItems().count() != 0); QTreeWidgetItem *listViewItem = linkList->currentItem(); bool isProtocolSelected = (listViewItem == 0 ? false : listViewItem->parent() == 0); btnRemoveProtocol->setEnabled(isProtocolSelected); btnAddMime->setEnabled(listViewItem != 0 && mimeList->selectedItems().count() != 0); btnRemoveMime->setEnabled(listViewItem == 0 ? false : listViewItem->parent() != 0); if (linkList->currentItem() == 0 && linkList->topLevelItemCount() != 0) linkList->setCurrentItem(linkList->topLevelItem(0)); QList list = linkList->selectedItems(); if (list.count() == 0 && linkList->currentItem() != 0) linkList->currentItem()->setSelected(true); } void KgProtocols::slotAddProtocol() { QList list = protocolList->selectedItems(); if (list.count() > 0) { addProtocol(list[ 0 ]->text(), true); slotDisableButtons(); emit sigChanged(); } } void KgProtocols::addProtocol(QString name, bool changeCurrent) { QList list = protocolList->findItems(name, Qt::MatchExactly); if (list.count() > 0) { delete list[ 0 ]; QTreeWidgetItem *listViewItem = new QTreeWidgetItem(linkList); listViewItem->setText(0, name); QString icon = KProtocolInfo::icon(name); if (icon.isEmpty()) icon = "go-next-view"; listViewItem->setIcon(0, krLoader->loadIcon(icon, KIconLoader::Small)); if (changeCurrent) linkList->setCurrentItem(listViewItem); } } void KgProtocols::slotRemoveProtocol() { QTreeWidgetItem *item = linkList->currentItem(); if (item) { removeProtocol(item->text(0)); slotDisableButtons(); emit sigChanged(); } } void KgProtocols::removeProtocol(QString name) { QList itemList = linkList->findItems(name, Qt::MatchExactly, 0); if (itemList.count()) { QTreeWidgetItem *item = itemList[ 0 ]; while (item->childCount() != 0) removeMime(item->child(0)->text(0)); linkList->takeTopLevelItem(linkList->indexOfTopLevelItem(item)); protocolList->addItem(name); protocolList->sortItems(); } } void KgProtocols::slotAddMime() { QList list = mimeList->selectedItems(); if (list.count() > 0 && linkList->currentItem() != 0) { QTreeWidgetItem *itemToAdd = linkList->currentItem(); if (itemToAdd->parent()) itemToAdd = itemToAdd->parent(); addMime(list[ 0 ]->text(), itemToAdd->text(0)); slotDisableButtons(); emit sigChanged(); } } void KgProtocols::addMime(QString name, QString protocol) { QList list = mimeList->findItems(name, Qt::MatchExactly); QList itemList = linkList->findItems(protocol, Qt::MatchExactly | Qt::MatchRecursive, 0); QTreeWidgetItem *currentListItem = 0; if (itemList.count() != 0) currentListItem = itemList[ 0 ]; if (list.count() > 0 && currentListItem && currentListItem->parent() == 0) { delete list[ 0 ]; QTreeWidgetItem *listViewItem = new QTreeWidgetItem(currentListItem); listViewItem->setText(0, name); listViewItem->setIcon(0, krLoader->loadMimeTypeIcon(name, KIconLoader::Small)); linkList->expandItem( currentListItem ); } } void KgProtocols::slotRemoveMime() { QTreeWidgetItem *item = linkList->currentItem(); if (item) { removeMime(item->text(0)); slotDisableButtons(); emit sigChanged(); } } void KgProtocols::removeMime(QString name) { QList itemList = linkList->findItems(name, Qt::MatchExactly | Qt::MatchRecursive, 0); QTreeWidgetItem *currentMimeItem = 0; if (itemList.count() != 0) currentMimeItem = itemList[ 0 ]; if (currentMimeItem && currentMimeItem->parent() != 0) { mimeList->addItem(currentMimeItem->text(0)); mimeList->sortItems(); currentMimeItem->parent()->removeChild(currentMimeItem); } } void KgProtocols::loadInitialValues() { if (linkList->model()->rowCount() > 0) while (linkList->topLevelItemCount() != 0) removeProtocol(linkList->topLevelItem(0)->text(0)); KConfigGroup group(krConfig, "Protocols"); QStringList protList = group.readEntry("Handled Protocols", QStringList()); for (QStringList::Iterator it = protList.begin(); it != protList.end(); ++it) { addProtocol(*it); QStringList mimes = group.readEntry(QString("Mimes For %1").arg(*it), QStringList()); for (QStringList::Iterator it2 = mimes.begin(); it2 != mimes.end(); ++it2) addMime(*it2, *it); } if (linkList->topLevelItemCount() != 0) linkList->setCurrentItem(linkList->topLevelItem(0)); slotDisableButtons(); linkList->expandAll(); emit sigChanged(); } void KgProtocols::setDefaults() { while (linkList->topLevelItemCount() != 0) removeProtocol(linkList->topLevelItem(0)->text(0)); slotDisableButtons(); if (isChanged()) emit sigChanged(); } bool KgProtocols::isChanged() { KConfigGroup group(krConfig, "Protocols"); QStringList protList = group.readEntry("Handled Protocols", QStringList()); if ((int)protList.count() != linkList->topLevelItemCount()) return true; for (int i = 0; i != linkList->topLevelItemCount(); i++) { QTreeWidgetItem *item = linkList->topLevelItem(i); if (!protList.contains(item->text(0))) return true; QStringList mimes = group.readEntry(QString("Mimes For %1").arg(item->text(0)), QStringList()); if ((int)mimes.count() != item->childCount()) return true; for (int j = 0; j != item->childCount(); j++) { QTreeWidgetItem *children = item->child(j); if (!mimes.contains(children->text(0))) return true; } } return false; } bool KgProtocols::apply() { KConfigGroup group(krConfig, "Protocols"); QStringList protocolList; for (int i = 0; i != linkList->topLevelItemCount(); i++) { QTreeWidgetItem *item = linkList->topLevelItem(i); protocolList.append(item->text(0)); QStringList mimes; for (int j = 0; j != item->childCount(); j++) { QTreeWidgetItem *children = item->child(j); mimes.append(children->text(0)); } group.writeEntry(QString("Mimes For %1").arg(item->text(0)), mimes); } group.writeEntry("Handled Protocols", protocolList); krConfig->sync(); KrServices::clearProtocolCache(); emit sigChanged(); return false; } void KgProtocols::init() { } diff --git a/krusader/Konfigurator/kgprotocols.h b/krusader/Konfigurator/kgprotocols.h index 13b41e7a..35d05602 100644 --- a/krusader/Konfigurator/kgprotocols.h +++ b/krusader/Konfigurator/kgprotocols.h @@ -1,83 +1,73 @@ -/*************************************************************************** - KgProtocols.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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 = 0); virtual void loadInitialValues() Q_DECL_OVERRIDE; virtual void setDefaults() Q_DECL_OVERRIDE; virtual bool apply() Q_DECL_OVERRIDE; virtual bool isChanged() Q_DECL_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(QString name, bool changeCurrent = false); void removeProtocol(QString name); void addMime(QString name, QString protocol); void removeMime(QString name); KrTreeWidget *linkList; KrListWidget *protocolList; KrListWidget *mimeList; QPushButton *btnAddProtocol; QPushButton *btnRemoveProtocol; QPushButton *btnAddMime; QPushButton *btnRemoveMime; }; #endif /* __KgProtocols_H__ */ diff --git a/krusader/Konfigurator/kgstartup.cpp b/krusader/Konfigurator/kgstartup.cpp index ceeed531..4cf73641 100644 --- a/krusader/Konfigurator/kgstartup.cpp +++ b/krusader/Konfigurator/kgstartup.cpp @@ -1,137 +1,127 @@ -/*************************************************************************** - kgstartup.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kgstartup.h" #include "../defaults.h" #include "../GUI/profilemanager.h" // QtWidgets #include #include #include #include KgStartup::KgStartup(bool first, QWidget* parent) : KonfiguratorPage(first, parent), profileCombo(0) { QWidget *innerWidget = new QFrame(this); setWidget(innerWidget); setWidgetResizable(true); QGridLayout *kgStartupLayout = new QGridLayout(innerWidget); kgStartupLayout->setSpacing(6); // --------------------------- PANELS GROUPBOX ---------------------------------- QGroupBox *panelsGrp = createFrame(i18n("General"), innerWidget); QGridLayout *panelsGrid = createGridLayout(panelsGrp); QString s = "

" + i18n("Defines the panel profile used at startup. A panel profile contains:
  • all the tabs paths
  • the current tab
  • the active panel
<Last session> is a special panel profile which is saved automatically when Krusader is closed."); QLabel *label = addLabel(panelsGrid, 0, 0, i18n("Startup profile:"), panelsGrp); label->setWhatsThis(s); panelsGrp->setWhatsThis(s); QStringList profileList = ProfileManager::availableProfiles("Panel"); profileList.push_front(i18n("")); const int profileListSize = profileList.size(); KONFIGURATOR_NAME_VALUE_PAIR *comboItems = new KONFIGURATOR_NAME_VALUE_PAIR[ profileListSize ]; for (int i = 0; i != profileListSize; i++) comboItems[ i ].text = comboItems[ i ].value = profileList [ i ]; comboItems[ 0 ].value = ""; profileCombo = createComboBox("Startup", "Starter Profile Name", comboItems[ 0 ].value, comboItems, profileListSize, panelsGrp, false, false); profileCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); panelsGrid->addWidget(profileCombo, 0, 1); delete [] comboItems; //------------------------------------------------ panelsGrid->addWidget(createLine(panelsGrp), 1, 0, 1, 2); KONFIGURATOR_CHECKBOX_PARAM settings[] = { // cfg_class cfg_name default text restart tooltip {"Look&Feel", "Show splashscreen", _ShowSplashScreen, i18n("Show splashscreen"), false, i18n("Display a splashscreen when starting Krusader.") }, {"Look&Feel", "Single Instance Mode", _SingleInstanceMode, i18n("Single instance mode"), false, i18n("Only one Krusader instance is allowed to run.") } }; KonfiguratorCheckBoxGroup* cbs = createCheckBoxGroup(2, 0, settings, 2 /* settings count */, panelsGrp); panelsGrid->addWidget(cbs, 2, 0, 1, 2); kgStartupLayout->addWidget(panelsGrp, 0, 0); // ------------------------ USERINTERFACE GROUPBOX ------------------------------ QGroupBox *uiGrp = createFrame(i18n("User Interface"), innerWidget); QGridLayout *uiGrid = createGridLayout(uiGrp); KONFIGURATOR_CHECKBOX_PARAM uiSettings[] = { // cfg_class cfg_name default text restart tooltip {"Startup", "Remember Position", _RememberPos,i18n("Save last position, size and panel settings"), false, i18n("

At startup, the main window will resize itself to the size it was when last shutdown. " "It will also appear in the same location of the screen, having panels sorted and aligned as they were before.

" "

If this option is disabled, you can use the menu Window -> Save Position option " "to manually set the main window's size and position at startup.

") }, {"Startup", "Update Default Panel Settings", _RememberPos, i18n("Update default panel settings"), true, i18n("When settings of a panel are changed, save them as the default for new panels of the same type.") }, {"Startup", "Start To Tray", _StartToTray, i18n("Start to tray"), false, i18n("Krusader starts to tray, without showing the main window") }, }; KonfiguratorCheckBoxGroup *uiSettingsGroup = createCheckBoxGroup(1, 0, uiSettings, 3, uiGrp); uiGrid->addWidget(uiSettingsGroup, 1, 0); KONFIGURATOR_CHECKBOX_PARAM uiCheckBoxes[] = { // cfg_class, cfg_name, default, text, restart, ToolTip {"Startup", "UI Save Settings", _UiSave, i18n("Save component settings on exit"), false, i18n("Check the state of the user interface components and restore them to their condition when last shutdown.") }, {"Startup", "Show FN Keys", _ShowFNkeys, i18n("Show function keys"), false, i18n("Function keys will be visible after startup.") }, {"Startup", "Show Cmd Line", _ShowCmdline, i18n("Show command line"), false, i18n("Command line will be visible after startup.") }, {"Startup", "Show Terminal Emulator", _ShowTerminalEmulator, i18n("Show embedded terminal"), false, i18n("Embedded terminal will be visible after startup.") }, }; uiCbGroup = createCheckBoxGroup(1, 0, uiCheckBoxes, 4, uiGrp); connect(uiCbGroup->find("UI Save Settings"), SIGNAL(stateChanged(int)), this, SLOT(slotDisable())); uiGrid->addWidget(uiCbGroup, 2, 0); slotDisable(); kgStartupLayout->addWidget(uiGrp, 1, 0); } void KgStartup::slotDisable() { bool isUiSave = !uiCbGroup->find("UI Save Settings")->isChecked(); int i = 1; while (uiCbGroup->find(i)) uiCbGroup->find(i++)->setEnabled(isUiSave); } diff --git a/krusader/Konfigurator/kgstartup.h b/krusader/Konfigurator/kgstartup.h index bf4af93e..af7b1de7 100644 --- a/krusader/Konfigurator/kgstartup.h +++ b/krusader/Konfigurator/kgstartup.h @@ -1,52 +1,42 @@ -/*************************************************************************** - kgstartup.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KGSTARTUP_H #define KGSTARTUP_H #include "konfiguratorpage.h" class KgStartup : public KonfiguratorPage { Q_OBJECT public: explicit KgStartup(bool first, QWidget* parent = 0); public slots: void slotDisable(); protected: KonfiguratorRadioButtons *saveRadio; KonfiguratorCheckBoxGroup *uiCbGroup; KonfiguratorComboBox *profileCombo; }; #endif /* __KGSTARTUP_H__ */ diff --git a/krusader/Konfigurator/kguseractions.cpp b/krusader/Konfigurator/kguseractions.cpp index 8603d11c..90a759e9 100644 --- a/krusader/Konfigurator/kguseractions.cpp +++ b/krusader/Konfigurator/kguseractions.cpp @@ -1,124 +1,114 @@ -/*************************************************************************** - kguseractions.cpp - description - ------------------- - copyright : (C) 2004 by Jonas B�r - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Jonas B�r * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kguseractions.h" #include "../defaults.h" #include "../ActionMan/actionman.h" // QtWidgets #include #include #include #include KgUserActions::KgUserActions(bool first, QWidget* parent) : KonfiguratorPage(first, parent) { QWidget *innerWidget = new QFrame(this); setWidget(innerWidget); setWidgetResizable(true); QGridLayout *kgUserActionLayout = new QGridLayout(innerWidget); // ============= Info Group ============= QGroupBox *InfoGroup = createFrame(i18n("Information"), innerWidget); QGridLayout *InfoGrid = createGridLayout(InfoGroup); // terminal for the UserActions QLabel *labelInfo = new QLabel(i18n( "Here you can configure settings about useractions.\n" "To set up, configure and manage your useractions please use ActionMan." ), InfoGroup); InfoGrid->addWidget(labelInfo, 0, 0); QPushButton *actionmanButton = new QPushButton(i18n("Start ActionMan"), InfoGroup); connect(actionmanButton, SIGNAL(clicked()), SLOT(startActionMan())); InfoGrid->addWidget(actionmanButton, 1, 0); kgUserActionLayout->addWidget(InfoGroup, 0 , 0); // ============= Terminal Group ============= QGroupBox *terminalGroup = createFrame(i18n("Terminal execution"), innerWidget); QGridLayout *terminalGrid = createGridLayout(terminalGroup); // terminal for the UserActions QLabel *labelTerminal = new QLabel(i18n("Terminal for UserActions:"), terminalGroup); terminalGrid->addWidget(labelTerminal, 0, 0); KonfiguratorURLRequester *urlReqUserActions = createURLRequester("UserActions", "Terminal", _UserActions_Terminal, terminalGroup, false, FIRST_PAGE, false); terminalGrid->addWidget(urlReqUserActions, 0, 1); labelTerminal = new QLabel(i18n("%t will be replaced by the title of the action,\n%d with the workdir."), terminalGroup); terminalGrid->addWidget(labelTerminal, 1, 1); kgUserActionLayout->addWidget(terminalGroup, 1 , 0); // ============= Outputcollection Group ============= QGroupBox *outputGroup = createFrame(i18n("Output collection"), innerWidget); QGridLayout *outputGrid = createGridLayout(outputGroup); QWidget *hboxWidget = new QWidget(outputGroup); QHBoxLayout *hbox = new QHBoxLayout(hboxWidget); QLabel *lbel = new QLabel(i18n("Normal font:"), hboxWidget); hbox->addWidget(lbel); KonfiguratorFontChooser *chser = createFontChooser("UserActions", "Normal Font", _UserActions_NormalFont, hboxWidget); hbox->addWidget(chser); QWidget *spcer = createSpacer(hboxWidget); hbox->addWidget(spcer); outputGrid->addWidget(hboxWidget, 2, 0); hboxWidget = new QWidget(outputGroup); hbox = new QHBoxLayout(hboxWidget); lbel = new QLabel(i18n("Font with fixed width:"), hboxWidget); hbox->addWidget(lbel); chser = createFontChooser("UserActions", "Fixed Font", _UserActions_FixedFont, hboxWidget); hbox->addWidget(chser); spcer = createSpacer(hboxWidget); hbox->addWidget(spcer); outputGrid->addWidget(hboxWidget, 3, 0); KonfiguratorCheckBox *useFixed = createCheckBox("UserActions", "Use Fixed Font", _UserActions_UseFixedFont, i18n("Use fixed width font as default"), outputGroup); outputGrid->addWidget(useFixed, 4, 0); kgUserActionLayout->addWidget(outputGroup, 2 , 0); } void KgUserActions::startActionMan() { ActionMan actionMan(static_cast(this)); } diff --git a/krusader/Konfigurator/kguseractions.h b/krusader/Konfigurator/kguseractions.h index 311bab03..fe3e43ed 100644 --- a/krusader/Konfigurator/kguseractions.h +++ b/krusader/Konfigurator/kguseractions.h @@ -1,48 +1,38 @@ -/*************************************************************************** - kguseractions.h - description - ------------------- - copyright : (C) 2004 by Jonas B�r - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Jonas B�r * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KGUSERACTIONS_H #define KGUSERACTIONS_H #include "konfiguratorpage.h" class KgUserActions : public KonfiguratorPage { Q_OBJECT public: explicit KgUserActions(bool first, QWidget* parent = 0); public slots: void startActionMan(); }; #endif /* __KGUSERACTIONS_H__ */ diff --git a/krusader/Konfigurator/konfigurator.cpp b/krusader/Konfigurator/konfigurator.cpp index 604baedf..d39aded4 100644 --- a/krusader/Konfigurator/konfigurator.cpp +++ b/krusader/Konfigurator/konfigurator.cpp @@ -1,250 +1,241 @@ -/*************************************************************************** - konfigurator.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "konfigurator.h" #include "../krglobal.h" #include "../Dialogs/krdialogs.h" #include "../kicons.h" // QtGui #include #include #include #include #include #include #include "../defaults.h" #include "../krusaderview.h" #include "../GUI/kfnkeys.h" // the frames #include "kgstartup.h" #include "kgpanel.h" #include "kggeneral.h" #include "kgadvanced.h" #include "kgarchives.h" #include "kgdependencies.h" #include "kgcolors.h" #include "kguseractions.h" #include "kgprotocols.h" Konfigurator::Konfigurator(bool f, int startPage) : KPageDialog((QWidget *)0), firstTime(f), internalCall(false), sizeX(-1), sizeY(-1) { setWindowTitle(i18n("Konfigurator - Creating Your Own Krusader")); setWindowModality(Qt::ApplicationModal); setFaceType(KPageDialog::List); setStandardButtons(QDialogButtonBox::Help|QDialogButtonBox::RestoreDefaults|QDialogButtonBox::Close| QDialogButtonBox::Apply|QDialogButtonBox::Reset); button(QDialogButtonBox::Apply)->setDefault(true); connect(button(QDialogButtonBox::Close), SIGNAL(clicked()), SLOT(slotClose())); connect(button(QDialogButtonBox::Help), SIGNAL(clicked()), SLOT(slotShowHelp())); connect(button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), SLOT(slotRestoreDefaults())); connect(button(QDialogButtonBox::Reset), SIGNAL(clicked()), SLOT(slotReset())); connect(button(QDialogButtonBox::Apply), SIGNAL(clicked()), SLOT(slotApply())); connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(slotPageSwitch(KPageWidgetItem*,KPageWidgetItem*))); connect(&restoreTimer, SIGNAL(timeout()), this, SLOT(slotRestorePage())); createLayout(startPage); KConfigGroup group(krConfig, "Konfigurator"); int sx = group.readEntry("Window Width", -1); int sy = group.readEntry("Window Height", -1); if (sx != -1 && sy != -1) resize(sx, sy); else resize(900, 680); if (group.readEntry("Window Maximized", false)) showMaximized(); else show(); } void Konfigurator::resizeEvent(QResizeEvent *e) { if (!isMaximized()) { sizeX = e->size().width(); sizeY = e->size().height(); } QDialog::resizeEvent(e); } void Konfigurator::closeDialog() { KConfigGroup group(krConfig, "Konfigurator"); group.writeEntry("Window Width", sizeX); group.writeEntry("Window Height", sizeY); group.writeEntry("Window Maximized", isMaximized()); } void Konfigurator::reject() { closeDialog(); QDialog::reject(); } void Konfigurator::newPage(KonfiguratorPage *page, const QString &name, const QString &desc, const QIcon &icon) { KPageWidgetItem *item = new KPageWidgetItem(page, name); item->setIcon(icon); item->setHeader(desc); addPage(item); kgPages.append(item); connect(page, SIGNAL(sigChanged()), this, SLOT(slotApplyEnable())); } void Konfigurator::createLayout(int startPage) { // startup newPage(new KgStartup(firstTime, this), i18n("Startup"), i18n("Krusader's settings upon startup"), QIcon::fromTheme("go-home")); // panel newPage(new KgPanel(firstTime, this), i18n("Panel"), i18n("Panel"), QIcon::fromTheme("view-choose")); // colors newPage(new KgColors(firstTime, this), i18n("Colors"), i18n("Colors"), QIcon::fromTheme("color-picker")); // general newPage(new KgGeneral(firstTime, this), i18n("General"), i18n("Basic Operations"), QIcon::fromTheme("system-run")); // advanced newPage(new KgAdvanced(firstTime, this), i18n("Advanced"), i18n("Be sure you know what you are doing."), QIcon::fromTheme("dialog-messages")); // archives newPage(new KgArchives(firstTime, this), i18n("Archives"), i18n("Customize the way Krusader deals with archives"), QIcon::fromTheme("archive-extract")); // dependencies newPage(new KgDependencies(firstTime, this), i18n("Dependencies"), i18n("Set the full path of the external applications"), QIcon::fromTheme("debug-run")); // useractions newPage(new KgUserActions(firstTime, this), i18n("User Actions"), i18n("Configure your personal actions"), QIcon::fromTheme("user-properties")); // protocols newPage(new KgProtocols(firstTime, this), i18n("Protocols"), i18n("Link MIMEs to protocols"), QIcon::fromTheme("document-preview")); setCurrentPage(kgPages.at(startPage)); slotApplyEnable(); } void Konfigurator::closeEvent(QCloseEvent *event) { lastPage = currentPage(); if(slotPageSwitch(lastPage, lastPage)) { hide(); KPageDialog::closeEvent(event); } else event->ignore(); } void Konfigurator::slotApplyEnable() { lastPage = currentPage(); bool isChanged = ((KonfiguratorPage *)(lastPage->widget()))->isChanged(); button(QDialogButtonBox::Apply)->setEnabled(isChanged); button(QDialogButtonBox::Reset)->setEnabled(isChanged); } bool Konfigurator::slotPageSwitch(KPageWidgetItem *current, KPageWidgetItem *before) { if (before == 0) return true; KonfiguratorPage *currentPg = (KonfiguratorPage *)(before->widget()); if (internalCall) { internalCall = false; return true; } if (currentPg->isChanged()) { int result = KMessageBox::questionYesNoCancel(0, i18n("The current page has been changed. Do you want to apply changes?")); switch (result) { case KMessageBox::No: currentPg->loadInitialValues(); currentPg->apply(); break; case KMessageBox::Yes: emit configChanged(currentPg->apply()); break; default: restoreTimer.setSingleShot(true); restoreTimer.start(0); return false; } } button(QDialogButtonBox::Apply)->setEnabled(currentPg->isChanged()); lastPage = current; return true; } void Konfigurator::slotRestorePage() { if (lastPage != currentPage()) { internalCall = true; setCurrentPage(lastPage); } } void Konfigurator::slotClose() { lastPage = currentPage(); if (slotPageSwitch(lastPage, lastPage)) { reject(); } } void Konfigurator::slotApply() { emit configChanged(((KonfiguratorPage*)(currentPage()->widget()))->apply()); } void Konfigurator::slotReset() { ((KonfiguratorPage *)(currentPage()->widget()))->loadInitialValues(); } void Konfigurator::slotRestoreDefaults() { ((KonfiguratorPage *)(currentPage()->widget()))->setDefaults(); } void Konfigurator::slotShowHelp() { KHelpClient::invokeHelp(QStringLiteral("konfigurator")); } diff --git a/krusader/Konfigurator/konfigurator.h b/krusader/Konfigurator/konfigurator.h index 0d0a7aa7..df36f736 100644 --- a/krusader/Konfigurator/konfigurator.h +++ b/krusader/Konfigurator/konfigurator.h @@ -1,88 +1,78 @@ -/*************************************************************************** - konfigurator.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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; 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; 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.cpp b/krusader/Konfigurator/konfiguratoritems.cpp index a5953689..a14917e7 100644 --- a/krusader/Konfigurator/konfiguratoritems.cpp +++ b/krusader/Konfigurator/konfiguratoritems.cpp @@ -1,846 +1,836 @@ -/*************************************************************************** - konfiguratoritems.cpp - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "konfiguratoritems.h" #include "../krglobal.h" // QtCore #include // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include #include KonfiguratorExtension::KonfiguratorExtension(QObject *obj, QString cfgGroup, QString cfgName, bool restartNeeded, int page) : QObject(), objectPtr(obj), applyConnected(false), setDefaultsConnected(false), changed(false), restartNeeded(restartNeeded), subpage(page), configGroup(cfgGroup), configName(cfgName) { } void KonfiguratorExtension::connectNotify(const QMetaMethod &signal) { if (signal == QMetaMethod::fromSignal(&KonfiguratorExtension::applyManually)) applyConnected = true; else if (signal == QMetaMethod::fromSignal(&KonfiguratorExtension::setDefaultsManually)) setDefaultsConnected = true; QObject::connectNotify(signal); } bool KonfiguratorExtension::apply() { if (!changed) return false; if (applyConnected) emit applyManually(objectPtr, configGroup, configName); else emit applyAuto(objectPtr, configGroup, configName); setChanged(false); return restartNeeded; } void KonfiguratorExtension::setDefaults() { if (setDefaultsConnected) emit setDefaultsManually(objectPtr); else emit setDefaultsAuto(objectPtr); } void KonfiguratorExtension::loadInitialValue() { emit setInitialValue(objectPtr); } bool KonfiguratorExtension::isChanged() { return changed; } // KonfiguratorCheckBox class /////////////////////////////// KonfiguratorCheckBox::KonfiguratorCheckBox(QString configGroup, QString name, bool defaultValue, QString text, QWidget *parent, bool restart, int page) : QCheckBox(text, parent), defaultValue(defaultValue) { ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); connect(this, SIGNAL(stateChanged(int)), ext, SLOT(setChanged())); loadInitialValue(); } KonfiguratorCheckBox::~KonfiguratorCheckBox() { delete ext; } void KonfiguratorCheckBox::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); setChecked(group.readEntry(ext->getConfigName(), defaultValue)); ext->setChanged(false); } void KonfiguratorCheckBox::checkStateSet() { QCheckBox::checkStateSet(); updateDeps(); } void KonfiguratorCheckBox::nextCheckState() { QCheckBox::nextCheckState(); updateDeps(); } void KonfiguratorCheckBox::addDep(KonfiguratorCheckBox *dep) { deps << dep; dep->setEnabled(isChecked()); } void KonfiguratorCheckBox::updateDeps() { foreach(KonfiguratorCheckBox *dep, deps) dep->setEnabled(isChecked()); } void KonfiguratorCheckBox::slotApply(QObject *, QString configGroup, QString name) { KConfigGroup(krConfig, configGroup).writeEntry(name, isChecked()); } void KonfiguratorCheckBox::slotSetDefaults(QObject *) { if (isChecked() != defaultValue) setChecked(defaultValue); } // KonfiguratorSpinBox class /////////////////////////////// KonfiguratorSpinBox::KonfiguratorSpinBox(QString configGroup, QString configName, int defaultValue, int min, int max, QWidget *parent, bool restartNeeded, int page) : QSpinBox(parent), defaultValue(defaultValue) { ext = new KonfiguratorExtension(this, configGroup, configName, restartNeeded, page); connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); connect(this, SIGNAL(valueChanged(int)), ext, SLOT(setChanged())); setMinimum(min); setMaximum(max); loadInitialValue(); } KonfiguratorSpinBox::~KonfiguratorSpinBox() { delete ext; } void KonfiguratorSpinBox::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); setValue(group.readEntry(ext->getConfigName(), defaultValue)); ext->setChanged(false); } void KonfiguratorSpinBox::slotApply(QObject *, QString configGroup, QString name) { KConfigGroup(krConfig, configGroup).writeEntry(name, value()); } void KonfiguratorSpinBox::slotSetDefaults(QObject *) { if (value() != defaultValue) setValue(defaultValue); } // KonfiguratorCheckBoxGroup class /////////////////////////////// void KonfiguratorCheckBoxGroup::add(KonfiguratorCheckBox *checkBox) { checkBoxList.append(checkBox); } KonfiguratorCheckBox * KonfiguratorCheckBoxGroup::find(int index) { if (index < 0 || index >= checkBoxList.count()) return 0; return checkBoxList.at(index); } KonfiguratorCheckBox * KonfiguratorCheckBoxGroup::find(QString name) { QListIterator it(checkBoxList); while (it.hasNext()) { KonfiguratorCheckBox * checkBox = it.next(); if (checkBox->extension()->getConfigName() == name) return checkBox; } return 0; } // KonfiguratorRadioButtons class /////////////////////////////// KonfiguratorRadioButtons::KonfiguratorRadioButtons(QString configGroup, QString name, QString defaultValue, QWidget *parent, bool restart, int page) : QWidget(parent), defaultValue(defaultValue) { ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); } KonfiguratorRadioButtons::~KonfiguratorRadioButtons() { delete ext; } void KonfiguratorRadioButtons::addRadioButton(QRadioButton *radioWidget, QString name, QString value) { radioButtons.append(radioWidget); radioNames.push_back(name); radioValues.push_back(value); connect(radioWidget, SIGNAL(toggled(bool)), ext, SLOT(setChanged())); } QRadioButton * KonfiguratorRadioButtons::find(int index) { if (index < 0 || index >= radioButtons.count()) return 0; return radioButtons.at(index); } QRadioButton * KonfiguratorRadioButtons::find(QString name) { int index = radioNames.indexOf(name); if (index == -1) return 0; return radioButtons.at(index); } void KonfiguratorRadioButtons::selectButton(QString value) { int cnt = 0; QListIterator it(radioButtons); while (it.hasNext()) { QRadioButton * btn = it.next(); if (value == radioValues[ cnt ]) { btn->setChecked(true); return; } cnt++; } if (!radioButtons.isEmpty()) radioButtons.first()->setChecked(true); } void KonfiguratorRadioButtons::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); QString initValue = group.readEntry(ext->getConfigName(), defaultValue); selectButton(initValue); ext->setChanged(false); } QString KonfiguratorRadioButtons::selectedValue() { int cnt = 0; QListIterator it(radioButtons); while (it.hasNext()) { QRadioButton * btn = it.next(); if (btn->isChecked()) { return radioValues[ cnt ]; } cnt++; } return QString(); } void KonfiguratorRadioButtons::slotApply(QObject *, QString configGroup, QString name) { QString value = selectedValue(); if (!value.isEmpty()) KConfigGroup(krConfig, configGroup).writeEntry(name, value); } void KonfiguratorRadioButtons::slotSetDefaults(QObject *) { selectButton(defaultValue); } // KonfiguratorEditBox class /////////////////////////////// KonfiguratorEditBox::KonfiguratorEditBox(QString configGroup, QString name, QString defaultValue, QWidget *parent, bool restart, int page) : QLineEdit(parent), defaultValue(defaultValue) { ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject *, QString, QString)), this, SLOT(slotApply(QObject *, QString, QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); connect(this, SIGNAL(textChanged(QString)), ext, SLOT(setChanged())); loadInitialValue(); } KonfiguratorEditBox::~KonfiguratorEditBox() { delete ext; } void KonfiguratorEditBox::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); setText(group.readEntry(ext->getConfigName(), defaultValue)); ext->setChanged(false); } void KonfiguratorEditBox::slotApply(QObject *, QString configGroup, QString name) { KConfigGroup(krConfig, configGroup).writeEntry(name, text()); } void KonfiguratorEditBox::slotSetDefaults(QObject *) { if (text() != defaultValue) setText(defaultValue); } // KonfiguratorURLRequester class /////////////////////////////// KonfiguratorURLRequester::KonfiguratorURLRequester(QString configGroup, QString name, QString defaultValue, QWidget *parent, bool restart, int page, bool expansion) : KUrlRequester(parent), defaultValue(defaultValue), expansion(expansion) { ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject *, QString, QString)), this, SLOT(slotApply(QObject *, QString, QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); connect(this, SIGNAL(textChanged(QString)), ext, SLOT(setChanged())); loadInitialValue(); } KonfiguratorURLRequester::~KonfiguratorURLRequester() { delete ext; } void KonfiguratorURLRequester::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); lineEdit()->setText(group.readEntry(ext->getConfigName(), defaultValue)); ext->setChanged(false); } void KonfiguratorURLRequester::slotApply(QObject *, QString configGroup, QString name) { KConfigGroup(krConfig, configGroup) .writeEntry(name, expansion ? url().toDisplayString(QUrl::PreferLocalFile) : text()); } void KonfiguratorURLRequester::slotSetDefaults(QObject *) { if (url().toDisplayString(QUrl::PreferLocalFile) != defaultValue) lineEdit()->setText(defaultValue); } // KonfiguratorFontChooser class /////////////////////////////// KonfiguratorFontChooser::KonfiguratorFontChooser(QString configGroup, QString name, QFont defaultValue, QWidget *parent, bool restart, int page) : QWidget(parent), defaultValue(defaultValue) { QHBoxLayout *layout = new QHBoxLayout(this); ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); pLabel = new QLabel(this); pLabel->setMinimumWidth(150); layout->addWidget(pLabel); pToolButton = new QToolButton(this); connect(pToolButton, SIGNAL(clicked()), this, SLOT(slotBrowseFont())); pToolButton->setIcon(SmallIcon("document-open")); layout->addWidget(pToolButton); loadInitialValue(); } KonfiguratorFontChooser::~KonfiguratorFontChooser() { delete ext; } void KonfiguratorFontChooser::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); font = group.readEntry(ext->getConfigName(), defaultValue); ext->setChanged(false); setFont(); } void KonfiguratorFontChooser::setFont() { pLabel->setFont(font); pLabel->setText(font.family() + QString(", %1").arg(font.pointSize())); } void KonfiguratorFontChooser::slotApply(QObject *, QString configGroup, QString name) { KConfigGroup(krConfig, configGroup).writeEntry(name, font); } void KonfiguratorFontChooser::slotSetDefaults(QObject *) { font = defaultValue; ext->setChanged(); setFont(); } void KonfiguratorFontChooser::slotBrowseFont() { bool ok; font = QFontDialog::getFont(&ok, font, this); if (!ok) return; // cancelled by the user, and font is actually not changed (getFont returns the font we gave it) ext->setChanged(); setFont(); } // KonfiguratorComboBox class /////////////////////////////// KonfiguratorComboBox::KonfiguratorComboBox(QString configGroup, QString name, QString defaultValue, KONFIGURATOR_NAME_VALUE_PAIR *listIn, int listInLen, QWidget *parent, bool restart, bool editable, int page) : QComboBox(parent), defaultValue(defaultValue), listLen(listInLen) { list = new KONFIGURATOR_NAME_VALUE_PAIR[ listInLen ]; for (int i = 0; i != listLen; i++) { list[i] = listIn[i]; addItem(list[i].text); } ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); // connect( this, SIGNAL(highlighted(int)), ext, SLOT(setChanged()) ); /* Removed because of startup combo failure */ connect(this, SIGNAL(activated(int)), ext, SLOT(setChanged())); connect(this, SIGNAL(currentTextChanged(QString)), ext, SLOT(setChanged())); setEditable(editable); loadInitialValue(); } KonfiguratorComboBox::~KonfiguratorComboBox() { delete []list; delete ext; } void KonfiguratorComboBox::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); QString select = group.readEntry(ext->getConfigName(), defaultValue); selectEntry(select); ext->setChanged(false); } void KonfiguratorComboBox::slotApply(QObject *, QString configGroup, QString name) { QString text = isEditable() ? lineEdit()->text() : currentText(); QString value = text; for (int i = 0; i != listLen; i++) if (list[i].text == text) { value = list[i].value; break; } KConfigGroup(krConfig, configGroup).writeEntry(name, value); } void KonfiguratorComboBox::selectEntry(QString entry) { for (int i = 0; i != listLen; i++) if (list[i].value == entry) { setCurrentIndex(i); return; } if (isEditable()) lineEdit()->setText(entry); else setCurrentIndex(0); } void KonfiguratorComboBox::slotSetDefaults(QObject *) { selectEntry(defaultValue); } // KonfiguratorColorChooser class /////////////////////////////// KonfiguratorColorChooser::KonfiguratorColorChooser(QString configGroup, QString name, QColor defaultValue, QWidget *parent, bool restart, ADDITIONAL_COLOR *addColPtr, int addColNum, int page) : QComboBox(parent), defaultValue(defaultValue), disableColorChooser(true) { ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); addColor(i18n("Custom color"), QColor(255, 255, 255)); addColor(i18nc("Default color", "Default"), defaultValue); for (int i = 0; i != addColNum; i++) { additionalColors.push_back(addColPtr[i]); addColor(addColPtr[i].name, addColPtr[i].color); } addColor(i18n("Red"), Qt::red); addColor(i18n("Green"), Qt::green); addColor(i18n("Blue"), Qt::blue); addColor(i18n("Cyan"), Qt::cyan); addColor(i18n("Magenta"), Qt::magenta); addColor(i18n("Yellow"), Qt::yellow); addColor(i18n("Dark Red"), Qt::darkRed); addColor(i18n("Dark Green"), Qt::darkGreen); addColor(i18n("Dark Blue"), Qt::darkBlue); addColor(i18n("Dark Cyan"), Qt::darkCyan); addColor(i18n("Dark Magenta"), Qt::darkMagenta); addColor(i18n("Dark Yellow"), Qt::darkYellow); addColor(i18n("White"), Qt::white); addColor(i18n("Light Gray"), Qt::lightGray); addColor(i18n("Gray"), Qt::gray); addColor(i18n("Dark Gray"), Qt::darkGray); addColor(i18n("Black"), Qt::black); connect(this, SIGNAL(activated(int)), this, SLOT(slotCurrentChanged(int))); loadInitialValue(); } KonfiguratorColorChooser::~KonfiguratorColorChooser() { delete ext; } QPixmap KonfiguratorColorChooser::createPixmap(QColor color) { QPainter painter; QPen pen; int size = QFontMetrics(font()).height() * 3 / 4; QRect rect(0, 0, size, size); QPixmap pixmap(rect.width(), rect.height()); pen.setColor(Qt::black); painter.begin(&pixmap); QBrush brush(color); painter.fillRect(rect, brush); painter.setPen(pen); painter.drawRect(rect); painter.end(); pixmap.detach(); return pixmap; } void KonfiguratorColorChooser::addColor(QString text, QColor color) { addItem(createPixmap(color), text); palette.push_back(color); } void KonfiguratorColorChooser::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); QString selected = group.readEntry(ext->getConfigName(), QString("")); setValue(selected); ext->setChanged(false); } void KonfiguratorColorChooser::setDefaultColor(QColor dflt) { defaultValue = dflt; palette[1] = defaultValue; setItemIcon(1, createPixmap(defaultValue)); if (currentIndex() == 1) emit colorChanged(); } void KonfiguratorColorChooser::changeAdditionalColor(int num, QColor color) { if (num < additionalColors.size()) { palette[2+num] = color; additionalColors[num].color = color; setItemIcon(2 + num, createPixmap(color)); if (currentIndex() == 2 + num) emit colorChanged(); } } void KonfiguratorColorChooser::setDefaultText(QString text) { setItemIcon(1, createPixmap(defaultValue)); setItemText(1, text); } void KonfiguratorColorChooser::slotApply(QObject *, QString configGroup, QString name) { KConfigGroup(krConfig, configGroup).writeEntry(name, getValue()); } void KonfiguratorColorChooser::setValue(QString value) { disableColorChooser = true; if (value.isEmpty()) { setCurrentIndex(1); customValue = defaultValue; } else { bool found = false; for (int j = 0; j != additionalColors.size(); j++) if (additionalColors[j].value == value) { setCurrentIndex(2 + j); found = true; break; } if (! found) { KConfigGroup colGroup(krConfig, ext->getConfigGroup()); colGroup.writeEntry("TmpColor", value); QColor color = colGroup.readEntry("TmpColor", defaultValue); customValue = color; colGroup.deleteEntry("TmpColor"); setCurrentIndex(0); for (int i = 2 + additionalColors.size(); i != palette.size(); i++) if (palette[i] == color) { setCurrentIndex(i); break; } } } palette[0] = customValue; setItemIcon(0, createPixmap(customValue)); ext->setChanged(); emit colorChanged(); disableColorChooser = false; } QString KonfiguratorColorChooser::getValue() { QColor color = palette[ currentIndex()]; if (currentIndex() == 1) /* it's the default value? */ return ""; else if (currentIndex() >= 2 && currentIndex() < 2 + additionalColors.size()) return additionalColors[ currentIndex() - 2 ].value; else return QString("%1,%2,%3").arg(color.red()).arg(color.green()).arg(color.blue()); } bool KonfiguratorColorChooser::isValueRGB() { return !(currentIndex() >= 1 && currentIndex() < 2 + additionalColors.size()); } void KonfiguratorColorChooser::slotSetDefaults(QObject *) { ext->setChanged(); setCurrentIndex(1); emit colorChanged(); } void KonfiguratorColorChooser::slotCurrentChanged(int number) { ext->setChanged(); if (number == 0 && !disableColorChooser) { QColor color = QColorDialog::getColor(customValue, this); if (color.isValid()) { disableColorChooser = true; customValue = color; palette[0] = customValue; setItemIcon(0, createPixmap(customValue)); disableColorChooser = false; } } emit colorChanged(); } QColor KonfiguratorColorChooser::getColor() { return palette[ currentIndex()]; } // KonfiguratorListBox class /////////////////////////////// KonfiguratorListBox::KonfiguratorListBox(QString configGroup, QString name, QStringList defaultValue, QWidget *parent, bool restart, int page) : KrListWidget(parent), defaultValue(defaultValue) { ext = new KonfiguratorExtension(this, configGroup, name, restart, page); connect(ext, SIGNAL(applyAuto(QObject*,QString,QString)), this, SLOT(slotApply(QObject*,QString,QString))); connect(ext, SIGNAL(setDefaultsAuto(QObject*)), this, SLOT(slotSetDefaults(QObject*))); connect(ext, SIGNAL(setInitialValue(QObject*)), this, SLOT(loadInitialValue())); loadInitialValue(); } KonfiguratorListBox::~KonfiguratorListBox() { delete ext; } void KonfiguratorListBox::loadInitialValue() { KConfigGroup group(krConfig, ext->getConfigGroup()); setList(group.readEntry(ext->getConfigName(), defaultValue)); ext->setChanged(false); } void KonfiguratorListBox::slotApply(QObject *, QString configGroup, QString name) { KConfigGroup(krConfig, configGroup).writeEntry(name, list()); } void KonfiguratorListBox::slotSetDefaults(QObject *) { if (list() != defaultValue) { ext->setChanged(); setList(defaultValue); } } void KonfiguratorListBox::setList(QStringList list) { clear(); addItems(list); } QStringList KonfiguratorListBox::list() { QStringList lst; for (int i = 0; i != count(); i++) lst += item(i)->text(); return lst; } void KonfiguratorListBox::addItem(const QString & item) { if (!list().contains(item)) { KrListWidget::addItem(item); ext->setChanged(); } } void KonfiguratorListBox::removeItem(const QString & item) { QList list = findItems(item, Qt::MatchExactly); for (int i = 0; i != list.count(); i++) delete list[ i ]; if (list.count()) ext->setChanged(); } diff --git a/krusader/Konfigurator/konfiguratoritems.h b/krusader/Konfigurator/konfiguratoritems.h index 83125065..e647d40c 100644 --- a/krusader/Konfigurator/konfiguratoritems.h +++ b/krusader/Konfigurator/konfiguratoritems.h @@ -1,437 +1,427 @@ -/*************************************************************************** - konfiguratoritems.h - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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; virtual void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; }; // KonfiguratorCheckBox class /////////////////////////////// class KonfiguratorCheckBox : public QCheckBox { Q_OBJECT public: KonfiguratorCheckBox(QString configGroup, QString name, bool defaultValue, QString text, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorCheckBox(); 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 *, QString, QString); void slotSetDefaults(QObject *); protected: virtual void checkStateSet(); virtual void nextCheckState(); 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 = 0, bool restartNeeded = false, int page = FIRST_PAGE); ~KonfiguratorSpinBox(); inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, QString); void slotSetDefaults(QObject *); protected: int defaultValue; KonfiguratorExtension *ext; }; // KonfiguratorCheckBoxGroup class /////////////////////////////// class KonfiguratorCheckBoxGroup : public QWidget { public: explicit KonfiguratorCheckBoxGroup(QWidget *parent = 0) : QWidget(parent){} void add(KonfiguratorCheckBox *); int count() { return checkBoxList.count(); }; KonfiguratorCheckBox * find(int index); KonfiguratorCheckBox * find(QString name); private: QList checkBoxList; }; // KonfiguratorRadioButtons class /////////////////////////////// class KonfiguratorRadioButtons : public QWidget { Q_OBJECT public: KonfiguratorRadioButtons(QString configGroup, QString name, QString defaultValue, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorRadioButtons(); inline KonfiguratorExtension *extension() { return ext; } void addRadioButton(QRadioButton *radioWidget, QString name, QString value); void selectButton(QString value); int count() { return radioButtons.count(); } QString selectedValue(); QRadioButton *find(int index); QRadioButton *find(QString name); public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, 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 = 0, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorEditBox(); inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, 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 = 0, bool restart = false, int page = FIRST_PAGE, bool expansion = true); ~KonfiguratorURLRequester(); inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, 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, QFont defaultValue, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorFontChooser(); inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, 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 = 0, bool restart = false, bool editable = false, int page = FIRST_PAGE); ~KonfiguratorComboBox(); inline KonfiguratorExtension *extension() { return ext; } public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, QString); void slotSetDefaults(QObject *); protected: QString defaultValue; KONFIGURATOR_NAME_VALUE_PAIR *list; int listLen; KonfiguratorExtension *ext; void selectEntry(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, QColor defaultValue, QWidget *parent = 0, bool restart = false, ADDITIONAL_COLOR *addColPtr = 0, int addColNum = 0, int page = FIRST_PAGE); ~KonfiguratorColorChooser(); inline KonfiguratorExtension *extension() { return ext; } void setDefaultColor(QColor dflt); void setDefaultText(QString text); QColor getColor(); void changeAdditionalColor(int num, QColor color); QString getValue(); bool isValueRGB(); void setValue(QString value); public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, QString); void slotSetDefaults(QObject *); void slotCurrentChanged(int number); signals: void colorChanged(); private: void addColor(QString text, QColor color); QPixmap createPixmap(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 = 0, bool restart = false, int page = FIRST_PAGE); ~KonfiguratorListBox(); inline KonfiguratorExtension *extension() { return ext; } void addItem(const QString &); void removeItem(const QString &); public slots: virtual void loadInitialValue(); void slotApply(QObject *, QString, QString); void slotSetDefaults(QObject *); protected: QStringList list(); void setList(QStringList); QStringList defaultValue; KonfiguratorExtension *ext; }; #endif /* __KONFIGURATOR_ITEMS_H__ */ diff --git a/krusader/Konfigurator/konfiguratorpage.cpp b/krusader/Konfigurator/konfiguratorpage.cpp index 89f4ca35..f0448cdb 100644 --- a/krusader/Konfigurator/konfiguratorpage.cpp +++ b/krusader/Konfigurator/konfiguratorpage.cpp @@ -1,294 +1,284 @@ -/* ************************************************************************** - konfiguratorpage.cpp - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "konfiguratorpage.h" // QtWidgets #include #include #include #include #include #include #include "../krglobal.h" KonfiguratorPage::KonfiguratorPage(bool firstTime, QWidget* parent) : QScrollArea(parent), firstCall(firstTime) { setFrameStyle(QFrame::NoFrame); } bool KonfiguratorPage::apply() { bool restartNeeded = false; for (QList::iterator item = itemList.begin(); item != itemList.end(); item ++) restartNeeded = (*item)->apply() || restartNeeded; krConfig->sync(); return restartNeeded; } void KonfiguratorPage::setDefaults() { int activePage = activeSubPage(); for (QList::iterator item = itemList.begin(); item != itemList.end(); item ++) { if ((*item)->subPage() == activePage) (*item)->setDefaults(); } } void KonfiguratorPage::loadInitialValues() { for (QList::iterator item = itemList.begin(); item != itemList.end(); item ++) (*item)->loadInitialValue(); } bool KonfiguratorPage::isChanged() { bool isChanged = false; for (QList::iterator item = itemList.begin(); item != itemList.end(); item ++) isChanged = isChanged || (*item)->isChanged(); return isChanged; } KonfiguratorCheckBox* KonfiguratorPage::createCheckBox(QString configGroup, QString name, bool defaultValue, QString text, QWidget *parent, bool restart, QString toolTip, int page) { KonfiguratorCheckBox *checkBox = new KonfiguratorCheckBox(configGroup, name, defaultValue, text, parent, restart, page); if (!toolTip.isEmpty()) checkBox->setWhatsThis(toolTip); registerObject(checkBox->extension()); return checkBox; } KonfiguratorSpinBox* KonfiguratorPage::createSpinBox(QString configGroup, QString configName, int defaultValue, int min, int max, QWidget *parent, bool restart, int page) { KonfiguratorSpinBox *spinBox = new KonfiguratorSpinBox(configGroup, configName, defaultValue, min, max, parent, restart, page); registerObject(spinBox->extension()); return spinBox; } KonfiguratorEditBox* KonfiguratorPage::createEditBox(QString configGroup, QString name, QString defaultValue, QWidget *parent, bool restart, int page) { KonfiguratorEditBox *editBox = new KonfiguratorEditBox(configGroup, name, defaultValue, parent, restart, page); registerObject(editBox->extension()); return editBox; } KonfiguratorListBox* KonfiguratorPage::createListBox(QString configGroup, QString name, QStringList defaultValue, QWidget *parent, bool restart, int page) { KonfiguratorListBox *listBox = new KonfiguratorListBox(configGroup, name, defaultValue, parent, restart, page); registerObject(listBox->extension()); return listBox; } KonfiguratorURLRequester* KonfiguratorPage::createURLRequester(QString configGroup, QString name, QString defaultValue, QWidget *parent, bool restart, int page, bool expansion) { KonfiguratorURLRequester *urlRequester = new KonfiguratorURLRequester(configGroup, name, defaultValue, parent, restart, page, expansion); registerObject(urlRequester->extension()); return urlRequester; } QGroupBox* KonfiguratorPage::createFrame(QString text, QWidget *parent) { QGroupBox *groupBox = new QGroupBox(parent); if (!text.isNull()) groupBox->setTitle(text); return groupBox; } QGridLayout* KonfiguratorPage::createGridLayout(QWidget *parent) { QGridLayout *gridLayout = new QGridLayout(parent); gridLayout->setAlignment(Qt::AlignTop); gridLayout->setSpacing(6); gridLayout->setContentsMargins(11, 11, 11, 11); return gridLayout; } QLabel* KonfiguratorPage::addLabel(QGridLayout *layout, int x, int y, QString label, QWidget *parent) { QLabel *lbl = new QLabel(label, parent); layout->addWidget(lbl, x, y); return lbl; } QWidget* KonfiguratorPage::createSpacer(QWidget *parent) { QWidget *widget = new QWidget(parent); QHBoxLayout *hboxlayout = new QHBoxLayout(widget); QSpacerItem* spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hboxlayout->addItem(spacer); return widget; } KonfiguratorCheckBoxGroup* KonfiguratorPage::createCheckBoxGroup(int sizex, int sizey, KONFIGURATOR_CHECKBOX_PARAM *params, int paramNum, QWidget *parent, int page) { KonfiguratorCheckBoxGroup *groupWidget = new KonfiguratorCheckBoxGroup(parent); QGridLayout *layout = new QGridLayout(groupWidget); layout->setSpacing(6); layout->setContentsMargins(0, 0, 0, 0); int x = 0, y = 0; for (int i = 0; i != paramNum; i++) { KonfiguratorCheckBox *checkBox = createCheckBox(params[i].configClass, params[i].configName, params[i].defaultValue, params[i].text, groupWidget, params[i].restart, params[i].toolTip, page); groupWidget->add(checkBox); layout->addWidget(checkBox, y, x); if (sizex) { if (++x == sizex) x = 0, y++; } else { if (++y == sizey) y = 0, x++; } } return groupWidget; } KonfiguratorRadioButtons* KonfiguratorPage::createRadioButtonGroup(QString configGroup, QString name, QString defaultValue, int sizex, int sizey, KONFIGURATOR_NAME_VALUE_TIP *params, int paramNum, QWidget *parent, bool restart, int page) { KonfiguratorRadioButtons *radioWidget = new KonfiguratorRadioButtons(configGroup, name, defaultValue, parent, restart, page); QGridLayout *layout = new QGridLayout(radioWidget); layout->setAlignment(Qt::AlignTop); layout->setSpacing(6); layout->setContentsMargins(0, 0, 0, 0); int x = 0, y = 0; for (int i = 0; i != paramNum; i++) { QRadioButton *radBtn = new QRadioButton(params[i].text, radioWidget); if (!params[i].tooltip.isEmpty()) radBtn->setWhatsThis(params[i].tooltip); layout->addWidget(radBtn, y, x); radioWidget->addRadioButton(radBtn, params[i].text, params[i].value); if (sizex) { if (++x == sizex) x = 0, y++; } else { if (++y == sizey) y = 0, x++; } } radioWidget->loadInitialValue(); registerObject(radioWidget->extension()); return radioWidget; } KonfiguratorFontChooser *KonfiguratorPage::createFontChooser(QString configGroup, QString name, QFont defaultValue, QWidget *parent, bool restart, int page) { KonfiguratorFontChooser *fontChooser = new KonfiguratorFontChooser(configGroup, name, defaultValue, parent, restart, page); registerObject(fontChooser->extension()); return fontChooser; } KonfiguratorComboBox *KonfiguratorPage::createComboBox(QString configGroup, QString name, QString defaultValue, KONFIGURATOR_NAME_VALUE_PAIR *params, int paramNum, QWidget *parent, bool restart, bool editable, int page) { KonfiguratorComboBox *comboBox = new KonfiguratorComboBox(configGroup, name, defaultValue, params, paramNum, parent, restart, editable, page); registerObject(comboBox->extension()); return comboBox; } QFrame* KonfiguratorPage::createLine(QWidget *parent, bool vertical) { QFrame *line = new QFrame(parent); line->setFrameStyle((vertical ? QFrame::VLine : QFrame::HLine) | QFrame::Sunken); return line; } void KonfiguratorPage::registerObject(KonfiguratorExtension *item) { itemList.push_back(item); connect(item, SIGNAL(sigChanged(bool)), this, SIGNAL(sigChanged())); } void KonfiguratorPage::removeObject(KonfiguratorExtension *item) { int ndx = itemList.indexOf(item); if (ndx != -1) { QList::iterator it = itemList.begin() + ndx; delete *it; itemList.erase(it); } } KonfiguratorColorChooser *KonfiguratorPage::createColorChooser(QString configGroup, QString name, QColor defaultValue, QWidget *parent, bool restart, ADDITIONAL_COLOR *addColPtr, int addColNum, int page) { KonfiguratorColorChooser *colorChooser = new KonfiguratorColorChooser(configGroup, name, defaultValue, parent, restart, addColPtr, addColNum, page); registerObject(colorChooser->extension()); return colorChooser; } diff --git a/krusader/Konfigurator/konfiguratorpage.h b/krusader/Konfigurator/konfiguratorpage.h index 7d5b276d..601f83ff 100644 --- a/krusader/Konfigurator/konfiguratorpage.h +++ b/krusader/Konfigurator/konfiguratorpage.h @@ -1,525 +1,515 @@ -/* ************************************************************************** - konfiguratorpage.h - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KONFIGURATORPAGE_H #define KONFIGURATORPAGE_H // QtWidgets #include #include #include #include #include #include "konfiguratoritems.h" struct KONFIGURATOR_CHECKBOX_PARAM; /** * KonfiguratorPage is responsible for handling pages in Konfigurator. * It provides simple methods for create and manage Konfigurator pages. * * @short The base class of a page in Konfigurator */ class KonfiguratorPage : public QScrollArea { Q_OBJECT public: /** * The constructor of the KonfiguratorPage class. * * @param firstTime this parameter is true if it is the first call of Konfigurator * @param parent reference to the parent widget */ KonfiguratorPage(bool firstTime, QWidget *parent); /** * Applies the changes in the Konfigurator page. * * Writes out all relevant information to the konfiguration object and synchronizes * it with the file storage (hard disk, krusaderrc file). This function calls the apply() * method of each konfigurator item and finally performs the synchronization. * * @return a boolean value indicates that Krusader restart is needed for the correct change */ virtual bool apply(); /** * Sets every konfigurator item to its default value on the page. * * This method calls the setDefaults() method of each konfigurator item. This function * doesn't modify the current configuration, only the values of the GUI items. The * apply() method must be called for finalizing the changes. */ virtual void setDefaults(); /** * Reloads the original value of each konfigurator item from the configuration object. * * This function calls the loadInitialValue() method of each konfigurator item. * Used to rollback the changes on the konfigurator page. Called if the user * responds 'No' to the "Apply changes" question. */ virtual void loadInitialValues(); /** * Checks whether the page was changed. * * This function calls the isChanged() method of each konfigurator item and * performs logical OR operation on them. Actually, this function returns true * if any of the konfigurator items was changed. * * @return true if at least one of the konfigurator items was changed */ virtual bool isChanged(); /** * Flag, indicates the first call of Konfigurator * @return true if konfigurator was started at the first time */ inline bool isFirst() { return firstCall; } /** * This method is used to query the active subpage from the Konfigurator * @return the active page (by default the first page) */ virtual int activeSubPage() { return FIRST_PAGE; } /** * Adds a new checkbox item to the page. *
The checkbox widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* KonfiguratorCheckBox *myCheckBox = createCheckBox( "class", "name", false, parentWidget);
* myLayout->addWidget( myCheckBox, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The item name used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the checkbox * @param text The text field of the checkbox * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param toolTip Tooltip used for this checkbox * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created checkbox */ KonfiguratorCheckBox *createCheckBox(QString configGroup, QString name, bool defaultValue, QString text, QWidget *parent = 0, bool restart = false, QString toolTip = QString(), int page = FIRST_PAGE); /** * Adds a new spinbox item to the page. *
The spinbox widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* KonfiguratorSpinBox *mySpinBox = createSpinBox( "class", "name", 10, 1, 100, parentWidget);
* myLayout->addWidget( mySpinBox, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The item name used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the spinbox * @param min The minimum value of the spinbox * @param max The maximum value of the spinbox * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created spinbox */ KonfiguratorSpinBox *createSpinBox(QString configGroup, QString configName, int defaultValue, int min, int max, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); /** * Adds a new editbox item to the page. *
The editbox widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* KonfiguratorEditBox *myEditBox = createEditBox( "class", "name", "default", parentWidget);
* myLayout->addWidget( myEditBox, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The itemname used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the editbox * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created editbox */ KonfiguratorEditBox *createEditBox(QString configGroup, QString name, QString defaultValue, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); /** * Adds a new listbox item to the page. *
The listbox widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* QStringList valueList;
* valueList += "item";
* KonfiguratorListBox *myListBox = createListBox( "class", "name", valueList, parentWidget);
* myLayout->addWidget( myListBox, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The itemname used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the listbox * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created editbox */ KonfiguratorListBox *createListBox(QString configGroup, QString name, QStringList defaultValue, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); /** * Adds a new URL requester item to the page. *
The URL requester widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* KonfiguratorURLRequester *myURLRequester = createURLRequester( "class", "name", "default", parentWidget );
* myLayout->addWidget( myURLRequester, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The itemname used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the URL requester * @param text The text field of the URL requester * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param page The subpage of a Konfigurator page (because of setDefaults) * @param expansion Whether to perform url espansion * * @return reference to the newly created URL requester */ KonfiguratorURLRequester *createURLRequester(QString configGroup, QString name, QString defaultValue, QWidget *parent, bool restart, int page = FIRST_PAGE, bool expansion = true); /** * Adds a new font chooser item to the page. *
The font chooser widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* KonfiguratorFontChooser *myFontChooser = createFontChooser( "class", "name", QFont(), parentWidget );
* myLayout->addWidget( myFontChooser, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The item name used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the font chooser * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created font chooser */ KonfiguratorFontChooser *createFontChooser(QString configGroup, QString name, QFont defaultValue, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); /** * Adds a new combobox item to the page. *
The combobox widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* KONFIGURATOR_NAME_VALUE_PAIR comboInfo[] =
*  {{ i18n( "combo text1" ), "value1" },
*   { i18n( "combo text2" ), "value2" },
*   { i18n( "combo text3" ), "value3" }};

* KonfiguratorComboBox *myComboBox = createComboBox( "class", "name", "value2", comboInfo, 3, parentWidget );
* myLayout->addWidget( myComboBox, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The item name used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the combobox * @param params Pointer to the name-value pair array (combo elements) * @param paramNum Number of the combobox elements * @param text The text field of the combobox * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param editable Flag indicates that the combo can be edited * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created combobox */ KonfiguratorComboBox *createComboBox(QString configGroup, QString name, QString defaultValue, KONFIGURATOR_NAME_VALUE_PAIR *params, int paramNum, QWidget *parent = 0, bool restart = false, bool editable = false, int page = FIRST_PAGE); /** * Creates a frame on the page. * * Sample:

* QGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );
* myLayout->addWidget( myGroup, 0, 0 ); * * @param text The text written out onto the frame * @param parent Reference to the parent widget * * @return reference to the newly created frame */ QGroupBox *createFrame(QString text = QString(), QWidget *parent = 0); /** * Creates a new QGridLayout element and sets its margins. * * Sample:

* QGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );
* QGridLayout *myLayout = createGridLayout( myGroup ) );
* myLayout->addWidget( myGroup, 0, 0 ); * * @param parent Reference to the parent layout * * @return reference to the newly created QGridLayout */ QGridLayout *createGridLayout(QWidget *parent); /** * Adds a new label to a grid layout. * * Sample:

* QGroupBox *myGroup = createFrame( i18n( "MyFrameName" ), parentWidget, "frameName" );
* QGridLayout *myLayout = createGridLayout( myGroup->layout() );
* addLabel( myLayout, 0, 0, i18n( "Hello world!" ), myGroup, "myLabel" );
* mainLayout->addWidget( myGroup, 0, 0 ); * * @param layout The grid layout on which the item will be placed * @param x the column to which the label will be placed * @param y the row to which the label will be placed * @param label the text of the label * @param parent Reference to the parent widget * * @return reference to the newly created label */ QLabel *addLabel(QGridLayout *layout, int x, int y, QString label, QWidget *parent = 0); /** * Creates a spacer object (for justifying in QHBox). * * Sample:

* QHBox *hbox = new QHBox( myParent, "hbox" );
* createSpinBox( "class", "spin", 5, 1, 10, hbox );
* createSpacer( hbox );
* myLayout->addWidget( hbox, 0, 0 ); * * @param parent Reference to the parent widget * * @return reference to the newly created spacer widget */ QWidget *createSpacer(QWidget *parent = 0); /** * Creates a separator line. * * Sample:

* QFrame *myLine = createLine( myParent, "myLine" );
* myLayout->addWidget( myLine, 1, 0 );
* * @param parent Reference to the parent widget * @param vertical Means vertical line * * @return reference to the newly created spacer widget */ QFrame *createLine(QWidget *parent = 0, bool vertical = false); /** * Creates a checkbox group. A checkbox group contains a lot of checkboxes. * The grouped checkboxes are embedded into one widget, which can be placed anywhere * on the GUI. The placing of the elements can be horizontal or vertical in the group. * At horizontal placing the sizex integer defines the maximum element number in * one row, sizey is 0. At vertical placing sizex is 0, and sizey defines the * maximum row number in one column.
* * One specific element can be reached by its name or index with the find methods. * The first element is checkBoxGroup->find( 0 ), "myCb" element is checkBoxGroup->find( "myCb") ... * * Sample:

* KONFIGURATOR_CHECKBOX_PARAM myCBArray[] =
*  {{"CbClass","CbName1", false, i18n( "name1" ), false, "tooltip1"},
*   {"CbClass","CbName2", true, i18n( "name2" ), false, "tooltip2"},
*   {"CbClass","CbName3", true, i18n( "name3" ), false, "tooltip3"}};

* KonfiguratorCheckBoxGroup *myCheckBoxGroup = createCheckBoxGroup( 1, 0, myCBArray, 3, myParent, "myCheckboxGroup" );
* myCheckBoxGroup->find( 0 )->setEnabled( false );

* myLayout->addWidget( myCheckBoxGroup, 0, 0 );
* * @param sizex the maximum column number at horizontal placing * @param sizey the maximum row number at vertical placing * @param params pointer to the checkbox array * @param paramNum number of the checkbox elements * @param parent Reference to the parent widget * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created checkbox group widget */ KonfiguratorCheckBoxGroup *createCheckBoxGroup(int sizex, int sizey, KONFIGURATOR_CHECKBOX_PARAM *params, int paramNum, QWidget *parent = 0, int page = FIRST_PAGE); /** * Creates a radio button group. A radio button group contains a lot of radio buttons. * The grouped buttons are embedded into one widget, which can be placed anywhere * on the GUI. The placing of the elements can be horizontal or vertical in the group. * At horizontal placing the sizex integer defines the maximum element number in * one row, sizey is 0. At vertical placing sizex is 0, and sizey defines the * maximum row number in one column.
* * The references of the buttons can be accessed by the find methods of KonfiguratorRadioButtons. * The first element is myRadioGrp->find( 0 ), "myRadio" element is myRadioGrp->find( "myRadio") ... * * Sample:

* KONFIGURATOR_NAME_VALUE_TIP radioInfo[] =
*  {{ i18n( "radio text1" ), "value1", i18n( "tooltip1" ) },
*   { i18n( "radio text2" ), "value2", i18n( "tooltip2" ) },
*   { i18n( "radio text3" ), "value3", i18n( "tooltip3" ) }};

* KonfiguratorRadioButtons *myRadioGroup = createRadioButtonGroup( "class", "name", "value1", * 1, 0, radioInfo, 3, myParent, "myRadioGroup" );
* myRadioGroup->find( i18n( "radio text1" ) )->setEnabled( false );
* myLayout->addWidget( myRadioGroup, 0, 0 );
* * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The item name used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the radio buttons * @param sizex the maximum column number at horizontal placing * @param sizey the maximum row number at vertical placing * @param params pointer to the checkbox array * @param paramNum number of the checkbox elements * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created radio button group widget */ KonfiguratorRadioButtons *createRadioButtonGroup(QString configGroup, QString name, QString defaultValue, int sizex, int sizey, KONFIGURATOR_NAME_VALUE_TIP *params, int paramNum, QWidget *parent = 0, bool restart = false, int page = FIRST_PAGE); /** * This function is used to insert new, unknown items into KonfiguratorPage. The * item must be derived from KonfiguratorExtension class, which have * isChanged(), apply(), setDefaults, loadInitialValue() methods. After that, the * object is properly handled by Konfigurator page. * * * @param item The item to be added to KonfiguratorPage */ void registerObject(KonfiguratorExtension *item); /** * This function is used to remove elements from KonfiguratorPage. * * Sample:

* KonfiguratorEditBox *myEditBox = createEditBox( "class", "name", "default", parentWidget);
* myLayout->addWidget( myEditBox, 0, 0 );
* removeObject( myEditBox->extension() ); * * After the removeObject myEditBox will be untouched at apply(), setDefaults(), isChanged(), * loadInitialValues() methods of the KonfiguratorPage. * * @param item The item to be removed from KonfiguratorPage */ void removeObject(KonfiguratorExtension *item); /** * Adds a new color chooser combobox item to the page. *
The chooser's widget's name is QString(configGroup + "/" + name).ascii()
* * Sample:

* KonfiguratorColorChooser *myColorChooser = createColorChooser( "class", "name", QColor( 255, 0, 255 ), parentWidget );
* myLayout->addWidget( myColorChooser, 0, 0 ); * * @param configGroup The class name used in KConfig (ex. "Archives") * @param name The item name used in KConfig (ex. "Do Tar") * @param defaultValue The default value of the color chooser * @param parent Reference to the parent widget * @param restart The change of this parameter requires Krusader restart * @param addColPtr The additional color values * @param restart Number of additional colors * @param page The subpage of a Konfigurator page (because of setDefaults) * * @return reference to the newly created combobox */ KonfiguratorColorChooser *createColorChooser(QString configGroup, QString name, QColor defaultValue, QWidget *parent = 0, bool restart = false, ADDITIONAL_COLOR *addColPtr = 0, int addColNum = 0, int page = FIRST_PAGE); signals: /** * The signal is emitted if the changed flag was modified in any konfigurator item. * Used for enabling/disabling the apply button. */ void sigChanged(); protected: QList itemList; private: bool firstCall; }; /** * KONFIGURATOR_CHECKBOX_PARAM is the basic item of checkbox arrays. It contains * every information related to a checkbox. */ struct KONFIGURATOR_CHECKBOX_PARAM { /** * The class used in KConfig (ex. "Archives") */ QString configClass; /** * The item name used in KConfig (ex. "Do Tar") */ QString configName; /** * The default value of the checkbox */ bool defaultValue; /** * The text field of the checkbox */ QString text; /** * The change of this parameter requires Krusader restart */ bool restart; /** * The checkbox's tooltip */ QString toolTip; }; #endif /* __KONFIGURATOR_PAGE_H__ */ diff --git a/krusader/Locate/locate.cpp b/krusader/Locate/locate.cpp index 5964722f..1c009c9b 100644 --- a/krusader/Locate/locate.cpp +++ b/krusader/Locate/locate.cpp @@ -1,702 +1,692 @@ -/*************************************************************************** - locate.cpp - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "locate.h" #include "../kractions.h" #include "../krglobal.h" #include "../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 "../kicons.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_UNUSED(supportedActs); QList urls; QList list = selectedItems(); QListIterator it(list); while (it.hasNext()) { QTreeWidgetItem * item = it.next(); urls.push_back(QUrl::fromLocalFile(item->text(0))); } if (urls.count() == 0) return; QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setImageData(FL_LOADICON("file")); mimeData->setUrls(urls); drag->setMimeData(mimeData); drag->start(); } }; KProcess * LocateDlg::updateProcess = 0; LocateDlg * LocateDlg::LocateDialog = 0; LocateDlg::LocateDlg() : QDialog(0), isFeedToListBox(false) { setWindowTitle(i18n("Krusader::Locate")); setWindowModality(Qt::NonModal); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); QGridLayout *grid = new QGridLayout(); grid->setSpacing(6); grid->setContentsMargins(11, 11, 11, 11); QWidget *hboxWidget = new QWidget(this); QHBoxLayout *hbox = new QHBoxLayout(hboxWidget); hbox->setContentsMargins(0, 0, 0, 0); QLabel *label = new QLabel(i18n("Search for:"), hboxWidget); hbox->addWidget(label); locateSearchFor = new KHistoryComboBox(false, hboxWidget); locateSearchFor->setMinimumContentsLength(10); hbox->addWidget(locateSearchFor); label->setBuddy(locateSearchFor); KConfigGroup group(krConfig, "Locate"); QStringList list = group.readEntry("Search For", QStringList()); locateSearchFor->setMaxCount(25); // remember 25 items locateSearchFor->setHistoryItems(list); locateSearchFor->setEditable(true); locateSearchFor->setDuplicatesEnabled(false); locateSearchFor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); locateSearchFor->lineEdit()->setFocus(); grid->addWidget(hboxWidget, 0, 0); QWidget *hboxWidget2 = new QWidget(this); QHBoxLayout * hbox2 = new QHBoxLayout(hboxWidget2); hbox2->setContentsMargins(0, 0, 0, 0); QSpacerItem* spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hbox2->addItem(spacer); dontSearchInPath = new QCheckBox(i18n("Do not search in path"), hboxWidget2); hbox2->addWidget(dontSearchInPath); dontSearchInPath->setChecked(group.readEntry("Don't Search In Path", false)); existingFiles = new QCheckBox(i18n("Show only the existing files"), hboxWidget2); existingFiles->setChecked(group.readEntry("Existing Files", false)); hbox2->addWidget(existingFiles); caseSensitive = new QCheckBox(i18n("Case Sensitive"), hboxWidget2); caseSensitive->setChecked(group.readEntry("Case Sensitive", false)); hbox2->addWidget(caseSensitive); grid->addWidget(hboxWidget2, 1, 0); QFrame *line1 = new QFrame(this); line1->setFrameStyle(QFrame::HLine | QFrame::Sunken); grid->addWidget(line1, 2, 0); resultList = new LocateListView(this); // create the main container resultList->setColumnCount(1); resultList->setHeaderLabel(i18n("Results")); resultList->setColumnWidth(0, QFontMetrics(resultList->font()).width("W") * 60); KConfigGroup gl(krConfig, "Look&Feel"); resultList->setFont(gl.readEntry("Filelist Font", _FilelistFont)); resultList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); resultList->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); resultList->header()->setSortIndicatorShown(false); resultList->setSortingEnabled(false); resultList->setSelectionMode(QAbstractItemView::ExtendedSelection); resultList->setDragEnabled(true); connect(resultList, SIGNAL(itemRightClicked(QTreeWidgetItem*,QPoint,int)), this, SLOT(slotRightClick(QTreeWidgetItem*,QPoint))); connect(resultList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotDoubleClick(QTreeWidgetItem*))); connect(resultList, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(slotDoubleClick(QTreeWidgetItem*))); 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(QIcon::fromTheme(QStringLiteral("system-search"))); locateButton->setDefault(true); buttonBox->addButton(locateButton, QDialogButtonBox::ActionRole); updateDbButton = new QPushButton(i18n("Update DB")); updateDbButton->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); buttonBox->addButton(updateDbButton, QDialogButtonBox::ActionRole); feedStopButton = new QPushButton; buttonBox->addButton(feedStopButton, QDialogButtonBox::ActionRole); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(locateButton, SIGNAL(clicked()), this, SLOT(slotLocate())); connect(updateDbButton, SIGNAL(clicked()), this, SLOT(slotUpdateDb())); connect(feedStopButton, SIGNAL(clicked()), this, SLOT(slotFeedStop())); updateButtons(false); if (updateProcess) { if (updateProcess->state() == QProcess::Running) { connect(updateProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(updateFinished())); updateDbButton->setEnabled(false); } else updateFinished(); } show(); LocateDialog = this; } void LocateDlg::slotFeedStop() /* The stop / feed to listbox button */ { if (isFeedToListBox) feedToListBox(); else locateProc->kill(); } void LocateDlg::slotUpdateDb() /* The Update DB button */ { if (!updateProcess) { KConfigGroup group(krConfig, "Locate"); updateProcess = new KProcess(); // don't set the parent to 'this'! That would cause this process to be deleted once the dialog is closed *updateProcess << KrServices::fullPathName("updatedb"); *updateProcess << KShell::splitArgs(group.readEntry("UpdateDB Arguments")); connect(updateProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(updateFinished())); updateProcess->start(); updateDbButton->setEnabled(false); } } void LocateDlg::updateFinished() { delete updateProcess; updateProcess = 0; updateDbButton->setEnabled(true); } void LocateDlg::slotLocate() /* The locate button */ { locateSearchFor->addToHistory(locateSearchFor->currentText()); QStringList list = locateSearchFor->historyItems(); KConfigGroup group(krConfig, "Locate"); group.writeEntry("Search For", list); group.writeEntry("Don't Search In Path", dontSearchPath = dontSearchInPath->isChecked()); group.writeEntry("Existing Files", onlyExist = existingFiles->isChecked()); group.writeEntry("Case Sensitive", isCs = caseSensitive->isChecked()); if (!KrServices::cmdExist("locate")) { KMessageBox::error(0, i18n("Cannot start 'locate'. Check the 'Dependencies' page in konfigurator.")); return; } resultList->clear(); lastItem = 0; remaining = ""; updateButtons(true); isFeedToListBox = false; resultList->setFocus(); qApp->processEvents(); //FIXME - whats's this for ? locateProc = new KProcess(this); locateProc->setOutputChannelMode(KProcess::SeparateChannels); // default is forwarding to the parent channels connect(locateProc, SIGNAL(readyReadStandardOutput()), SLOT(processStdout())); connect(locateProc, SIGNAL(readyReadStandardError()), SLOT(processStderr())); connect(locateProc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(locateFinished())); connect(locateProc, SIGNAL(error(QProcess::ProcessError)), SLOT(locateError())); *locateProc << KrServices::fullPathName("locate"); if (!isCs) *locateProc << "-i"; *locateProc << (pattern = locateSearchFor->currentText()); if (!pattern.startsWith('*')) pattern = '*' + pattern; if (!pattern.endsWith('*')) pattern = pattern + '*'; collectedErr = ""; locateProc->start(); } void LocateDlg::locateError() { if (locateProc->error() == QProcess::FailedToStart) KMessageBox::error(krMainWindow, i18n("Error during the start of 'locate' process.")); } void LocateDlg::locateFinished() { if (locateProc->exitStatus() != QProcess::NormalExit || locateProc->exitStatus()) { if (!collectedErr.isEmpty()) KMessageBox::error(krMainWindow, i18n("Locate produced the following error message:\n\n%1", collectedErr)); } if (resultList->topLevelItemCount() == 0) { locateSearchFor->setFocus(); isFeedToListBox = false; } else { isFeedToListBox = true; } updateButtons(false); } void LocateDlg::processStdout() { remaining += QString::fromLocal8Bit(locateProc->readAllStandardOutput()); QStringList list = remaining.split('\n'); int items = list.size(); for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) { if (--items == 0 && !remaining.endsWith('\n')) remaining = *it; else { if (dontSearchPath) { QRegExp regExp(pattern, isCs ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); QString fileName = (*it).trimmed(); if (fileName.endsWith(QLatin1String("/")) && fileName != "/") { fileName.truncate(fileName.length() - 1); } fileName = fileName.mid(fileName.lastIndexOf('/') + 1); if (!regExp.exactMatch(fileName)) continue; } if (onlyExist) { KFileItem file(QUrl::fromLocalFile((*it).trimmed())); if (!file.isReadable()) continue; } if (lastItem) lastItem = new QTreeWidgetItem(resultList, lastItem); else lastItem = new QTreeWidgetItem(resultList); lastItem->setText(0, *it); } } } void LocateDlg::processStderr() { collectedErr += QString::fromLocal8Bit(locateProc->readAllStandardError()); } void LocateDlg::slotRightClick(QTreeWidgetItem *item, const QPoint &pos) { if (!item) return; // create the menu QMenu popup; popup.setTitle(i18nc("@title:menu", "Locate")); QAction * actView = popup.addAction(i18n("View (F3)")); QAction * actEdit = popup.addAction(i18n("Edit (F4)")); QAction * actComp = popup.addAction(i18n("Compare by content (F10)")); if (resultList->selectedItems().count() != 2) actComp->setEnabled(false); popup.addSeparator(); QAction * actFind = popup.addAction(i18n("Find (Ctrl+F)")); QAction * actNext = popup.addAction(i18n("Find next (Ctrl+N)")); QAction * actPrev = popup.addAction(i18n("Find previous (Ctrl+P)")); popup.addSeparator(); QAction * actClip = popup.addAction(i18n("Copy selected to clipboard")); QAction * result = popup.exec(pos); int ret = -1; if (result == actView) ret = VIEW_ID; else if (result == actEdit) ret = EDIT_ID; else if (result == actFind) ret = FIND_ID; else if (result == actNext) ret = FIND_NEXT_ID; else if (result == actPrev) ret = FIND_PREV_ID; else if (result == actClip) ret = COPY_SELECTED_TO_CLIPBOARD; else if (result == actComp) ret = COMPARE_ID; if (ret != - 1) operate(item, ret); } void LocateDlg::slotDoubleClick(QTreeWidgetItem *item) { if (!item) return; QString dirName = item->text(0); QString fileName; if (!QDir(dirName).exists()) { fileName = dirName.mid(dirName.lastIndexOf('/') + 1); dirName.truncate(dirName.lastIndexOf('/')); } ACTIVE_FUNC->openUrl(QUrl::fromLocalFile(dirName), fileName); QDialog::accept(); } void LocateDlg::keyPressEvent(QKeyEvent *e) { if (KrGlobal::copyShortcut == QKeySequence(e->key() | e->modifiers())) { operate(0, COPY_SELECTED_TO_CLIPBOARD); e->accept(); return; } switch (e->key()) { case Qt::Key_M : if (e->modifiers() == Qt::ControlModifier) { resultList->setFocus(); e->accept(); } break; case Qt::Key_F3 : if (resultList->currentItem()) operate(resultList->currentItem(), VIEW_ID); break; case Qt::Key_F4 : if (resultList->currentItem()) operate(resultList->currentItem(), EDIT_ID); break; case Qt::Key_F10 : operate(0, COMPARE_ID); break; case Qt::Key_N : if (e->modifiers() == Qt::ControlModifier) operate(resultList->currentItem(), FIND_NEXT_ID); break; case Qt::Key_P : if (e->modifiers() == Qt::ControlModifier) operate(resultList->currentItem(), FIND_PREV_ID); break; case Qt::Key_F : if (e->modifiers() == Qt::ControlModifier) operate(resultList->currentItem(), FIND_ID); break; } QDialog::keyPressEvent(e); } void LocateDlg::operate(QTreeWidgetItem *item, int task) { QUrl name; if (item != 0) name = QUrl::fromLocalFile(item->text(0)); switch (task) { case VIEW_ID: KrViewer::view(name, this); // view the file break; case EDIT_ID: KrViewer::edit(name, this); // view the file break; case COMPARE_ID: { QList list = resultList->selectedItems(); if (list.count() != 2) break; QUrl url1 = QUrl::fromLocalFile(list[ 0 ]->text(0)); QUrl url2 = QUrl::fromLocalFile(list[ 1 ]->text(0)); SLOTS->compareContent(url1,url2); } break; case FIND_ID: { KConfigGroup group(krConfig, "Locate"); long options = group.readEntry("Find Options", (long long)0); QStringList list = group.readEntry("Find Patterns", QStringList()); QPointer dlg = new KFindDialog(this, options, list); if (dlg->exec() != QDialog::Accepted) { delete dlg; return; } QString first; if (list.count() != 0) { first = list.first(); } if (first != (findPattern = dlg->pattern())) { list.push_front(dlg->pattern()); } group.writeEntry("Find Options", (long long)(findOptions = dlg->options())); group.writeEntry("Find Patterns", list); if (!(findOptions & KFind::FromCursor) && resultList->topLevelItemCount()) resultList->setCurrentItem((findOptions & KFind::FindBackwards) ? resultList->topLevelItem(resultList->topLevelItemCount() - 1) : resultList->topLevelItem(0)); findCurrentItem = resultList->currentItem(); if (find() && findCurrentItem) { resultList->selectionModel()->clearSelection(); // HACK: QT 4 is not able to paint the focus frame because of a bug resultList->setCurrentItem(findCurrentItem); } else { KMessageBox::information(this, i18n("Search string not found.")); } resultList->scrollTo(resultList->currentIndex()); delete dlg; } break; case FIND_NEXT_ID: case FIND_PREV_ID: { if (task == FIND_PREV_ID) findOptions ^= KFind::FindBackwards; findCurrentItem = resultList->currentItem(); nextLine(); if (find() && findCurrentItem) { resultList->selectionModel()->clearSelection(); // HACK: QT 4 is not able to paint the focus frame because of a bug resultList->setCurrentItem(findCurrentItem); } else KMessageBox::information(this, i18n("Search string not found.")); resultList->scrollTo(resultList->currentIndex()); if (task == FIND_PREV_ID) findOptions ^= KFind::FindBackwards; } break; case COPY_SELECTED_TO_CLIPBOARD: { QList urls; QTreeWidgetItemIterator it(resultList); while (*it) { if ((*it)->isSelected()) urls.push_back(QUrl::fromLocalFile((*it)->text(0))); it++; } if (urls.count() == 0) return; QMimeData *mimeData = new QMimeData; mimeData->setImageData(FL_LOADICON("file")); mimeData->setUrls(urls); QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); } break; } } void LocateDlg::nextLine() { if (findOptions & KFind::FindBackwards) findCurrentItem = resultList->itemAbove(findCurrentItem); else findCurrentItem = resultList->itemBelow(findCurrentItem); } bool LocateDlg::find() { while (findCurrentItem) { QString item = findCurrentItem->text(0); if (findOptions & KFind::RegularExpression) { if (item.contains(QRegExp(findPattern, ((findOptions & KFind::CaseSensitive) != 0) ? Qt::CaseSensitive : Qt::CaseInsensitive))) return true; } else { if (item.contains(findPattern, ((findOptions & KFind::CaseSensitive) != 0) ? Qt::CaseSensitive : Qt::CaseInsensitive)) return true; } nextLine(); } return false; } void LocateDlg::feedToListBox() { VirtualFileSystem virtFilesystem; virtFilesystem.scanDir(QUrl::fromLocalFile(QStringLiteral("/"))); KConfigGroup group(krConfig, "Locate"); int listBoxNum = group.readEntry("Feed To Listbox Counter", 1); QString queryName; do { queryName = i18n("Locate results") + QString(" %1").arg(listBoxNum++); } while (virtFilesystem.getFileItem(queryName) != 0); group.writeEntry("Feed To Listbox Counter", listBoxNum); KConfigGroup ga(krConfig, "Advanced"); if (ga.readEntry("Confirm Feed to Listbox", _ConfirmFeedToListbox)) { bool ok; queryName = QInputDialog::getText(this, i18n("Query Name"), i18n("Here you can name the file collection:"), QLineEdit::Normal, queryName, &ok); if (! ok) return; } QList urlList; QTreeWidgetItemIterator it(resultList); while (*it) { QTreeWidgetItem * item = *it; urlList.push_back(QUrl::fromLocalFile(item->text(0))); it++; } QUrl url = QUrl(QStringLiteral("virt:/") + queryName); virtFilesystem.refresh(url); // create directory if it does not exist virtFilesystem.addFiles(urlList); //ACTIVE_FUNC->openUrl(url); ACTIVE_MNG->slotNewTab(url); accept(); } void LocateDlg::reset() { locateSearchFor->lineEdit()->setFocus(); locateSearchFor->lineEdit()->selectAll(); } void LocateDlg::updateButtons(bool locateIsRunning) { locateButton->setEnabled(!locateIsRunning); if (locateIsRunning) { feedStopButton->setEnabled(true); feedStopButton->setText(i18n("Stop")); feedStopButton->setIcon(QIcon::fromTheme(QStringLiteral("process-stop"))); } else { if (resultList->topLevelItemCount() == 0) { feedStopButton->setEnabled(false); feedStopButton->setText(i18n("Stop")); feedStopButton->setIcon(QIcon::fromTheme(QStringLiteral("process-stop"))); } else { feedStopButton->setEnabled(true); feedStopButton->setText(i18n("Feed to listbox")); feedStopButton->setIcon(QIcon::fromTheme(QStringLiteral("list-add"))); } } } diff --git a/krusader/Locate/locate.h b/krusader/Locate/locate.h index f35c1bdc..3a4914e2 100644 --- a/krusader/Locate/locate.h +++ b/krusader/Locate/locate.h @@ -1,116 +1,106 @@ -/*************************************************************************** - locate.h - description - ------------------- - copyright : (C) 2004 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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: LocateDlg(); 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; 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/kmountman.cpp b/krusader/MountMan/kmountman.cpp index 3f4c16d6..56aae039 100644 --- a/krusader/MountMan/kmountman.cpp +++ b/krusader/MountMan/kmountman.cpp @@ -1,506 +1,499 @@ -/*************************************************************************** - kmountman.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kmountman.h" // QtCore #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../krglobal.h" #include "../kractions.h" #include "../defaults.h" #include "../Dialogs/krdialogs.h" #include "../krservices.h" #include "kmountmangui.h" #include "../FileSystem/krpermhandler.h" #ifdef _OS_SOLARIS_ #define FSTAB "/etc/filesystemtab" #else #define FSTAB "/etc/fstab" #endif KMountMan::KMountMan(QWidget *parent) : QObject(), _operational(false), waiting(false), mountManGui(0), parentWindow(parent) { _action = new KToolBarPopupAction(QIcon::fromTheme("kr_mountman"), i18n("&MountMan..."), this); connect(_action, &QAction::triggered, this, &KMountMan::mainWindow); connect(_action->menu(), &QMenu::aboutToShow, this, &KMountMan::quickList); _manageAction = _action->menu()->addAction(i18n("Open &MountMan")); connect(_manageAction, &QAction::triggered, this, &KMountMan::mainWindow); _action->menu()->addSeparator(); // added as a precaution, although we use kde services now _operational = KrServices::cmdExist("mount"); network_fs << "nfs" << "smbfs" << "fuse.fusesmb" << "fuse.sshfs"; //TODO: is this list complete ? // list of FS that we don't manage at all invalid_fs << "swap" << "/dev/pts" << "tmpfs" << "devpts" << "sysfs" << "rpc_pipefs" << "usbfs" << "binfmt_misc"; #ifdef BSD invalid_fs << "procfs"; #else invalid_fs << "proc"; #endif // list of FS that we don't allow to mount/unmount nonmount_fs << "supermount"; { KConfigGroup group(krConfig, "Advanced"); QStringList nonmount = group.readEntry("Nonmount Points", _NonMountPoints).split(','); nonmount_fs_mntpoint += nonmount; // simplify the white space for (QStringList::Iterator it = nonmount_fs_mntpoint.begin(); it != nonmount_fs_mntpoint.end(); ++it) { *it = (*it).simplified(); } } } KMountMan::~KMountMan() {} bool KMountMan::invalidFilesystem(QString type) { return (invalid_fs.contains(type) > 0); } // this is an ugly hack, but type can actually be a mountpoint. oh well... bool KMountMan::nonmountFilesystem(QString type, QString mntPoint) { return((nonmount_fs.contains(type) > 0) || (nonmount_fs_mntpoint.contains(mntPoint) > 0)); } bool KMountMan::networkFilesystem(QString type) { return (network_fs.contains(type) > 0); } void KMountMan::mainWindow() { // left as a precaution, although we use kde's services now if (!KrServices::cmdExist("mount")) { KMessageBox::error(0, i18n("Cannot start 'mount'. Check the 'Dependencies' page in konfigurator.")); return; } mountManGui = new KMountManGUI(this); delete mountManGui; /* as KMountManGUI is modal, we can now delete it */ mountManGui = nullptr; /* for sanity */ } QExplicitlySharedDataPointer KMountMan::findInListByMntPoint(KMountPoint::List &lst, QString value) { if (value.length() > 1 && value.endsWith('/')) value = value.left(value.length() - 1); QExplicitlySharedDataPointer m; for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) { m = it->data(); QString mntPnt = m->mountPoint(); if (mntPnt.length() > 1 && mntPnt.endsWith('/')) mntPnt = mntPnt.left(mntPnt.length() - 1); if (mntPnt == value) return m; } return QExplicitlySharedDataPointer(); } void KMountMan::jobResult(KJob *job) { waiting = false; if (job->error()) job->uiDelegate()->showErrorMessage(); } void KMountMan::mount(QString mntPoint, bool blocking) { QString udi = findUdiForPath(mntPoint, Solid::DeviceInterface::StorageAccess); if (!udi.isNull()) { Solid::Device device(udi); Solid::StorageAccess *access = device.as(); if (access && !access->isAccessible()) { connect(access, &Solid::StorageAccess::setupDone, this, &KMountMan::slotSetupDone, Qt::UniqueConnection); if (blocking) waiting = true; // prepare to block access->setup(); } } else { KMountPoint::List possible = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions); QExplicitlySharedDataPointer m = findInListByMntPoint(possible, mntPoint); if (!((bool)m)) return; if (blocking) waiting = true; // prepare to block // KDE4 doesn't allow mounting devices as user, because they think it's the right behaviour. // I add this patch, as I don't think so. if (geteuid()) { // tries to mount as an user? KProcess proc; proc << KrServices::fullPathName("mount") << mntPoint; proc.start(); if (!blocking) return; proc.waitForFinished(-1); // -1 msec blocks without timeout if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) return; } KIO::SimpleJob *job = KIO::mount(false, m->mountType().toLocal8Bit(), m->mountedFrom(), m->mountPoint(), KIO::DefaultFlags); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); connect(job, SIGNAL(result(KJob*)), this, SLOT(jobResult(KJob*))); } while (blocking && waiting) { qApp->processEvents(); usleep(1000); } } void KMountMan::unmount(QString mntPoint, bool blocking) { //if working dir is below mountpoint cd to ~ first if(QUrl::fromLocalFile(QDir(mntPoint).canonicalPath()).isParentOf(QUrl::fromLocalFile(QDir::current().canonicalPath()))) QDir::setCurrent(QDir::homePath()); QString udi = findUdiForPath(mntPoint, Solid::DeviceInterface::StorageAccess); if (!udi.isNull()) { Solid::Device device(udi); Solid::StorageAccess *access = device.as(); if (access && access->isAccessible()) { connect(access, &Solid::StorageAccess::teardownDone, this, &KMountMan::slotTeardownDone, Qt::UniqueConnection); access->teardown(); } } else { if (blocking) waiting = true; // prepare to block // KDE4 doesn't allow unmounting devices as user, because they think it's the right behaviour. // I add this patch, as I don't think so. if (geteuid()) { // tries to mount as an user? KProcess proc; proc << KrServices::fullPathName("umount") << mntPoint; proc.start(); if (!blocking) return; proc.waitForFinished(-1); // -1 msec blocks without timeout if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) return; } KIO::SimpleJob *job = KIO::unmount(mntPoint, KIO::DefaultFlags); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); connect(job, SIGNAL(result(KJob*)), this, SLOT(jobResult(KJob*))); } while (blocking && waiting) { qApp->processEvents(); usleep(1000); } } KMountMan::mntStatus KMountMan::getStatus(QString mntPoint) { QExplicitlySharedDataPointer mountPoint; // 1: is it already mounted KMountPoint::List current = KMountPoint::currentMountPoints(); mountPoint = findInListByMntPoint(current, mntPoint); if ((bool) mountPoint) return MOUNTED; // 2: is it a mount point but not mounted? KMountPoint::List possible = KMountPoint::possibleMountPoints(); mountPoint = findInListByMntPoint(possible, mntPoint); if ((bool) mountPoint) return NOT_MOUNTED; // 3: unknown return DOESNT_EXIST; } void KMountMan::toggleMount(QString mntPoint) { mntStatus status = getStatus(mntPoint); switch (status) { case MOUNTED: unmount(mntPoint); break; case NOT_MOUNTED: mount(mntPoint); break; case DOESNT_EXIST: // do nothing: no-op to make the compiler quiet ;-) break; } } void KMountMan::autoMount(QString path) { KConfigGroup group(krConfig, "Advanced"); if (!group.readEntry("AutoMount", _AutoMount)) return; // auto mount disabled if (getStatus(path) == NOT_MOUNTED) mount(path); } void KMountMan::eject(QString mntPoint) { QString udi = findUdiForPath(mntPoint, Solid::DeviceInterface::OpticalDrive); if (udi.isNull()) return; Solid::Device dev(udi); Solid::OpticalDrive *drive = dev.as(); if (drive == 0) return; //if working dir is below mountpoint cd to ~ first if(QUrl::fromLocalFile(QDir(mntPoint).canonicalPath()).isParentOf(QUrl::fromLocalFile(QDir::current().canonicalPath()))) QDir::setCurrent(QDir::homePath()); connect(drive, SIGNAL(ejectDone(Solid::ErrorType,QVariant,QString)), this, SLOT(slotTeardownDone(Solid::ErrorType,QVariant,QString))); drive->eject(); } // returns true if the path is an ejectable mount point (at the moment CDROM and DVD) bool KMountMan::ejectable(QString path) { QString udi = findUdiForPath(path, Solid::DeviceInterface::OpticalDisc); if (udi.isNull()) return false; Solid::Device dev(udi); return dev.as() != 0; } bool KMountMan::removable(QString path) { QString udi = findUdiForPath(path, Solid::DeviceInterface::StorageAccess); if (udi.isNull()) return false; return removable(Solid::Device(udi)); } bool KMountMan::removable(Solid::Device d) { if(!d.isValid()) return false; Solid::StorageDrive *drive = d.as(); if(drive) return drive->isRemovable(); else return(removable(d.parent())); } // a mountMan special version of KIO::convertSize, which deals // with large filesystems ==> > 4GB, it actually receives size in // a minimum block of 1024 ==> data is KB not bytes QString KMountMan::convertSize(KIO::filesize_t size) { float fsize; QString s; QLocale loc; // Tera-byte if (size >= 1073741824) { fsize = (float) size / (float) 1073741824; if (fsize > 1024) // no name for something bigger than tera byte // let's call it Zega-Byte, who'll ever find out? :-) s = i18n("%1 ZB", loc.toString(fsize / (float) 1024, 'f', 1)); else s = i18n("%1 TB", loc.toString(fsize, 'f', 1)); } // Giga-byte else if (size >= 1048576) { fsize = (float) size / (float) 1048576; s = i18n("%1 GB", loc.toString(fsize, 'f', 1)); } // Mega-byte else if (size > 1024) { fsize = (float) size / (float) 1024; s = i18n("%1 MB", loc.toString(fsize, 'f', 1)); } // Kilo-byte else { fsize = (float) size; s = i18n("%1 KB", loc.toString(fsize, 'f', 0)); } return s; } // populate the pop-up menu of the mountman tool-button with actions void KMountMan::quickList() { if (!_operational) { KMessageBox::error(0, i18n("MountMan is not operational. Sorry")); return; } // clear mount / unmount actions for (QAction *action : _action->menu()->actions()) { if (action == _manageAction || action->isSeparator()) { continue; } _action->menu()->removeAction(action); } // create lists of current and possible mount points const KMountPoint::List currentMountPoints = KMountPoint::currentMountPoints(); // create a menu, displaying mountpoints with possible actions for (QExplicitlySharedDataPointer possibleMountPoint : KMountPoint::possibleMountPoints()) { // skip nonmountable file systems if (nonmountFilesystem(possibleMountPoint->mountType(), possibleMountPoint->mountPoint()) || invalidFilesystem(possibleMountPoint->mountType())) { continue; } // does the mountpoint exist in current list? // if so, it can only be umounted, otherwise, it can be mounted bool needUmount = false; for (QExplicitlySharedDataPointer currentMountPoint : currentMountPoints) { if (currentMountPoint->mountPoint() == possibleMountPoint->mountPoint()) { // found -> needs umount needUmount = true; break; } } // add the item to the menu const QString text = QString("%1 %2 (%3)").arg(needUmount ? i18n("Unmount") : i18n("Mount"), possibleMountPoint->mountPoint(), possibleMountPoint->mountedFrom()); QAction *act = _action->menu()->addAction(text); act->setData(QList({ QVariant(needUmount ? KMountMan::ActionType::Unmount : KMountMan::ActionType::Mount), QVariant(possibleMountPoint->mountPoint()) })); } connect(_action->menu(), &QMenu::triggered, this, &KMountMan::delayedPerformAction); } void KMountMan::delayedPerformAction(const QAction *action) { if (!action || !action->data().canConvert>()) { return; } disconnect(_action->menu(), &QMenu::triggered, 0, 0); const QList actData = action->data().toList(); const int actionType = actData[0].toInt(); const QString mountPoint = actData[1].toString(); QTimer::singleShot(0, this, [=] { if (actionType == KMountMan::ActionType::Mount) { mount(mountPoint); } else { unmount(mountPoint); } }); } QString KMountMan::findUdiForPath(QString path, const Solid::DeviceInterface::Type &expType) { KMountPoint::List current = KMountPoint::currentMountPoints(); KMountPoint::List possible = KMountPoint::possibleMountPoints(); QExplicitlySharedDataPointer mp = findInListByMntPoint(current, path); if (!(bool)mp) { mp = findInListByMntPoint(possible, path); if (!(bool)mp) return QString(); } QString dev = QDir(mp->mountedFrom()).canonicalPath(); QList storageDevices = Solid::Device::listFromType(Solid::DeviceInterface::Block); for (int p = storageDevices.count() - 1 ; p >= 0; p--) { Solid::Device device = storageDevices[ p ]; QString udi = device.udi(); Solid::Block * sb = device.as(); if (sb) { QString devb = QDir(sb->device()).canonicalPath(); if (expType != Solid::DeviceInterface::Unknown && !device.isDeviceInterface(expType)) continue; if (devb == dev) return udi; } } return QString(); } QString KMountMan::pathForUdi(QString udi) { Solid::Device device(udi); Solid::StorageAccess *access = device.as(); if(access) return access->filePath(); else return QString(); } void KMountMan::slotTeardownDone(Solid::ErrorType error, QVariant errorData, const QString& /*udi*/) { waiting = false; if (error != Solid::NoError && errorData.isValid()) { KMessageBox::sorry(parentWindow, errorData.toString()); } } void KMountMan::slotSetupDone(Solid::ErrorType error, QVariant errorData, const QString& /*udi*/) { waiting = false; if (error != Solid::NoError && errorData.isValid()) { KMessageBox::sorry(parentWindow, errorData.toString()); } } diff --git a/krusader/MountMan/kmountman.h b/krusader/MountMan/kmountman.h index a0e12d51..559589ac 100644 --- a/krusader/MountMan/kmountman.h +++ b/krusader/MountMan/kmountman.h @@ -1,127 +1,118 @@ -/*************************************************************************** - kmountman.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KMOUNTMAN_H #define KMOUNTMAN_H // QtCore #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include class KMountManGUI; class KToolBarPopupAction; class KMountMan : public QObject { Q_OBJECT friend class KMountManGUI; public: enum mntStatus {DOESNT_EXIST, NOT_MOUNTED, MOUNTED}; inline bool operational() { return _operational; } // check this 1st void mount(QString mntPoint, bool blocking = true); // this is probably what you need for mount void unmount(QString mntPoint, bool blocking = true); // this is probably what you need for unmount mntStatus getStatus(QString mntPoint); // return the status of a mntPoint (if any) void eject(QString mntPoint); bool ejectable(QString path); bool removable(QString path); bool removable(Solid::Device d); QString convertSize(KIO::filesize_t size); bool invalidFilesystem(QString type); bool networkFilesystem(QString type); bool nonmountFilesystem(QString type, QString mntPoint); QAction *action() { return (QAction *) _action; } explicit KMountMan(QWidget *parent); ~KMountMan(); // NOTE: this function needs some time (~50msec) QString findUdiForPath(QString path, const Solid::DeviceInterface::Type &expType = Solid::DeviceInterface::Unknown); QString pathForUdi(QString udi); public slots: void mainWindow(); // opens up the GUI void autoMount(QString path); // just call it before refreshing into a dir void delayedPerformAction(const QAction *action); void quickList(); protected slots: void jobResult(KJob *job); void slotTeardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi); void slotSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi); protected: // used internally static QExplicitlySharedDataPointer findInListByMntPoint(KMountPoint::List &lst, QString value); void toggleMount(QString mntPoint); void emitRefreshPanel(const QUrl &url) { emit refreshPanel(url); } signals: void refreshPanel(const QUrl &); private: enum ActionType { Mount, Unmount }; KToolBarPopupAction *_action; QAction *_manageAction; bool _operational; // if false, something went terribly wrong on startup bool waiting; // used to block krusader while waiting for (un)mount operation KMountManGUI *mountManGui; // the following is the FS type QStringList invalid_fs; QStringList nonmount_fs; QStringList network_fs; // the following is the FS name QStringList nonmount_fs_mntpoint; QPointer parentWindow; }; #endif diff --git a/krusader/MountMan/kmountmangui.cpp b/krusader/MountMan/kmountmangui.cpp index 14dad625..d55d5e08 100644 --- a/krusader/MountMan/kmountmangui.cpp +++ b/krusader/MountMan/kmountmangui.cpp @@ -1,540 +1,531 @@ -/*************************************************************************** - kmountmangui.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kmountmangui.h" #include "../krglobal.h" #include "../Dialogs/krspecialwidgets.h" #include "../kicons.h" #include "../defaults.h" #include "../FileSystem/filesystem.h" // QtCore #include #include #include // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef BSD #define MTAB "/etc/mtab" #endif KMountManGUI::KMountManGUI(KMountMan *mntMan) : QDialog(mntMan->parentWindow), mountMan(mntMan), info(0), mountList(0), cbShowOnlyRemovable(0), watcher(0), sizeX(-1), sizeY(-1) { setWindowTitle(i18n("MountMan - Your Mount-Manager")); setWindowModality(Qt::WindowModal); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); watcher = new QTimer(this); connect(watcher, SIGNAL(timeout()), this, SLOT(checkMountChange())); mainLayout->addLayout(createMainPage()); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); mainLayout->addWidget(buttonBox); ejectButton = new QPushButton(i18n("&Eject")); ejectButton->setIcon(QIcon::fromTheme(QStringLiteral("media-eject"))); ejectButton->setEnabled(false); buttonBox->addButton(ejectButton, QDialogButtonBox::ActionRole); mountButton = new QPushButton(i18n("&Unmount")); mountButton->setEnabled(false); buttonBox->addButton(mountButton, QDialogButtonBox::ActionRole); // connections connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); connect(ejectButton, SIGNAL(clicked()), SLOT(slotEject())); connect(mountButton, SIGNAL(clicked()), SLOT(slotToggleMount())); connect(mountList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(doubleClicked(QTreeWidgetItem*))); connect(mountList, SIGNAL(itemRightClicked(QTreeWidgetItem*,QPoint,int)), this, SLOT(clicked(QTreeWidgetItem*,QPoint))); connect(mountList, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(changeActive(QTreeWidgetItem*))); connect(mountList, SIGNAL(itemSelectionChanged()), this, SLOT(changeActive())); KConfigGroup group(krConfig, "MountMan"); int sx = group.readEntry("Window Width", -1); int sy = group.readEntry("Window Height", -1); if (sx != -1 && sy != -1) resize(sx, sy); else resize(600, 300); if (group.readEntry("Window Maximized", false)) showMaximized(); else show(); getSpaceData(); exec(); } KMountManGUI::~KMountManGUI() { watcher->stop(); delete watcher; KConfigGroup group(krConfig, "MountMan"); group.writeEntry("Window Width", sizeX); group.writeEntry("Window Height", sizeY); group.writeEntry("Window Maximized", isMaximized()); group.writeEntry("Last State", mountList->header()->saveState()); group.writeEntry("ShowOnlyRemovable", cbShowOnlyRemovable->isChecked()); } void KMountManGUI::resizeEvent(QResizeEvent *e) { if (!isMaximized()) { sizeX = e->size().width(); sizeY = e->size().height(); } QDialog::resizeEvent(e); } QLayout *KMountManGUI::createMainPage() { QGridLayout *layout = new QGridLayout(); layout->setSpacing(10); mountList = new KrTreeWidget(this); // create the main container KConfigGroup grp(krConfig, "Look&Feel"); mountList->setFont(grp.readEntry("Filelist Font", _FilelistFont)); mountList->setSelectionMode(QAbstractItemView::SingleSelection); mountList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); mountList->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); QStringList labels; labels << i18n("Name"); labels << i18n("Type"); labels << i18n("Mnt.Point"); labels << i18n("Total Size"); labels << i18n("Free Size"); labels << i18n("Free %"); mountList->setHeaderLabels(labels); mountList->header()->setSectionResizeMode(QHeaderView::Interactive); grp = KConfigGroup(krConfig, "MountMan"); if (grp.hasKey("Last State")) mountList->header()->restoreState(grp.readEntry("Last State", QByteArray())); else { int i = QFontMetrics(mountList->font()).width("W"); int j = QFontMetrics(mountList->font()).width("0"); j = (i > j ? i : j); mountList->setColumnWidth(0, j*8); mountList->setColumnWidth(1, j*4); mountList->setColumnWidth(2, j*8); mountList->setColumnWidth(3, j*6); mountList->setColumnWidth(4, j*6); mountList->setColumnWidth(5, j*5); } mountList->setAllColumnsShowFocus(true); mountList->header()->setSortIndicatorShown(true); mountList->sortItems(0, Qt::AscendingOrder); // now the list is created, time to fill it with data. //=>mountMan->forceUpdate(); QGroupBox *box = new QGroupBox(i18n("MountMan.Info"), this); box->setAlignment(Qt::AlignHCenter); QVBoxLayout *vboxl = new QVBoxLayout(box); info = new KRFSDisplay(box); vboxl->addWidget(info); info->resize(info->width(), height()); cbShowOnlyRemovable = new QCheckBox(i18n("Show only removable devices"), this); cbShowOnlyRemovable->setChecked(grp.readEntry("ShowOnlyRemovable", false)); connect(cbShowOnlyRemovable , SIGNAL(stateChanged(int)), SLOT(updateList())); layout->addWidget(box, 0, 0); layout->addWidget(cbShowOnlyRemovable, 1, 0); layout->addWidget(mountList, 0, 1, 2, 1); return layout; } void KMountManGUI::getSpaceData() { fileSystems.clear(); KrMountDetector::getInstance()->hasMountsChanged(); mounted = KMountPoint::currentMountPoints(); possible = KMountPoint::possibleMountPoints(); if (mounted.size() == 0) { // nothing is mounted addNonMounted(); updateList(); // let's continue return; } for (KMountPoint::List::iterator it = mounted.begin(); it != mounted.end(); ++it) { // don't bother with invalid file systems if (mountMan->invalidFilesystem((*it)->mountType())) { continue; } KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo((*it) ->mountPoint()); if(!info.isValid()) { continue; } fsData data; data.setMntPoint((*it) ->mountPoint()); data.setMounted(true); data.setTotalBlks(info.size() / 1024); data.setFreeBlks(info.available() / 1024); data.setName((*it)->mountedFrom()); data.setType((*it)->mountType()); fileSystems.append(data); } addNonMounted(); updateList(); } void KMountManGUI::addNonMounted() { // handle the non-mounted ones for (KMountPoint::List::iterator it = possible.begin(); it != possible.end(); ++it) { // make sure we don't add things we've already added if (KMountMan::findInListByMntPoint(mounted, (*it)->mountPoint())) { continue; } else { fsData data; data.setMntPoint((*it)->mountPoint()); data.setMounted(false); data.setType((*it)->mountType()); data.setName((*it)->mountedFrom()); if (mountMan->invalidFilesystem(data.type())) continue; fileSystems.append(data); } } } void KMountManGUI::addItemToMountList(KrTreeWidget *lst, fsData &fs) { Solid::Device device(mountMan->findUdiForPath(fs.mntPoint(), Solid::DeviceInterface::StorageAccess)); if (cbShowOnlyRemovable->isChecked() && !mountMan->removable(device)) return; bool mtd = fs.mounted(); QString tSize = QString("%1").arg(KIO::convertSizeFromKiB(fs.totalBlks())); QString fSize = QString("%1").arg(KIO::convertSizeFromKiB(fs.freeBlks())); QString sPrct = QString("%1%").arg(100 - (fs.usedPerct())); QTreeWidgetItem *item = new QTreeWidgetItem(lst); item->setText(0, fs.name()); item->setText(1, fs.type()); item->setText(2, fs.mntPoint()); item->setText(3, (mtd ? tSize : QString("N/A"))); item->setText(4, (mtd ? fSize : QString("N/A"))); item->setText(5, (mtd ? sPrct : QString("N/A"))); Solid::StorageVolume *vol = device.as (); QString icon; if(device.isValid()) icon = device.icon(); else if(mountMan->networkFilesystem(fs.type())) icon = "folder-remote"; QStringList overlays; if (mtd) { overlays << "emblem-mounted"; } else { overlays << QString(); // We have to guarantee the placement of the next emblem } if (vol && vol->usage() == Solid::StorageVolume::Encrypted) { overlays << "security-high"; } item->setIcon(0, KDE::icon(icon, overlays)); } void KMountManGUI::updateList() { QString currentMP; int currentIdx = 0; QTreeWidgetItem *currentItem = mountList->currentItem(); if(currentItem) { currentMP = getMntPoint(currentItem); currentIdx = mountList->indexOfTopLevelItem(currentItem); } mountList->clearSelection(); mountList->clear(); for (QList::iterator it = fileSystems.begin(); it != fileSystems.end() ; ++it) addItemToMountList(mountList, *it); currentItem = mountList->topLevelItem(currentIdx); for(int i = 0; i < mountList->topLevelItemCount(); i++) { QTreeWidgetItem *item = mountList->topLevelItem(i); if(getMntPoint(item) == currentMP) currentItem = item; } if(!currentItem) currentItem = mountList->topLevelItem(0); mountList->setCurrentItem(currentItem); changeActive(currentItem); mountList->setFocus(); watcher->setSingleShot(true); watcher->start(WATCHER_DELAY); // starting the watch timer ( single shot ) } void KMountManGUI::checkMountChange() { if (KrMountDetector::getInstance()->hasMountsChanged()) getSpaceData(); watcher->setSingleShot(true); watcher->start(WATCHER_DELAY); // starting the watch timer ( single shot ) } void KMountManGUI::doubleClicked(QTreeWidgetItem *i) { if (!i) return; // we don't want to refresh to swap, do we ? // change the active panel to this mountpoint mountMan->emitRefreshPanel(QUrl::fromLocalFile(getMntPoint(i))); close(); } void KMountManGUI::changeActive() { QList seld = mountList->selectedItems(); if (seld.count() > 0) changeActive(seld[ 0 ]); } // when user clicks on a filesystem, change information void KMountManGUI::changeActive(QTreeWidgetItem *i) { if (!i) { if (info) { info->setEmpty(true); info->update(); } mountButton->setEnabled(false); ejectButton->setEnabled(false); return; } fsData *system = getFsData(i); info->setAlias(system->mntPoint()); info->setRealName(system->name()); info->setMounted(system->mounted()); info->setEmpty(false); info->setTotalSpace(system->totalBlks()); info->setFreeSpace(system->freeBlks()); info->repaint(); if(system->mounted()) mountButton->setText(i18n("&Unmount")); else mountButton->setText(i18n("&Mount")); ejectButton->setEnabled(mountMan->ejectable(system->mntPoint())); mountButton->setEnabled(true); } // called when right-clicked on a filesystem void KMountManGUI::clicked(QTreeWidgetItem *item, const QPoint & pos) { // these are the values that will exist in the menu #define MOUNT_ID 90 #define UNMOUNT_ID 91 #define FORMAT_ID 93 #define EJECT_ID 94 ////////////////////////////////////////////////////////// if (!item) return; fsData *system = getFsData(item); // create the menu QMenu popup; popup.setTitle(i18n("MountMan")); if (!system->mounted()) { QAction *mountAct = popup.addAction(i18n("Mount")); mountAct->setData(QVariant(MOUNT_ID)); bool enable = !(mountMan->nonmountFilesystem(system->type(), system->mntPoint())); mountAct->setEnabled(enable); } else { QAction * umountAct = popup.addAction(i18n("Unmount")); umountAct->setData(QVariant(UNMOUNT_ID)); bool enable = !(mountMan->nonmountFilesystem(system->type(), system->mntPoint())); umountAct->setEnabled(enable); } if (mountMan->ejectable(system->mntPoint())) // if (system->type()=="iso9660" || mountMan->followLink(system->name()).left(2)=="cd") popup.addAction(i18n("Eject"))->setData(QVariant(EJECT_ID)); else { QAction *formatAct = popup.addAction(i18n("Format")); formatAct->setData(QVariant(FORMAT_ID)); formatAct->setEnabled(false); } QString mountPoint = system->mntPoint(); QAction * res = popup.exec(pos); int result = -1; if (res && res->data().canConvert()) result = res->data().toInt(); // check out the user's option switch (result) { case - 1 : return ; // the user clicked outside of the menu case MOUNT_ID : case UNMOUNT_ID : mountMan->toggleMount(mountPoint); break; case FORMAT_ID : break; case EJECT_ID : mountMan->eject(mountPoint); break; } } void KMountManGUI::slotToggleMount() { QTreeWidgetItem *item = mountList->currentItem(); if(item) { mountMan->toggleMount(getFsData(item)->mntPoint()); } } void KMountManGUI::slotEject() { QTreeWidgetItem *item = mountList->currentItem(); if(item) { mountMan->eject(getFsData(item)->mntPoint()); } } fsData* KMountManGUI::getFsData(QTreeWidgetItem *item) { for (QList::Iterator it = fileSystems.begin(); it != fileSystems.end(); ++it) { // the only thing which is unique is the mount point if ((*it).mntPoint() == getMntPoint(item)) { return & (*it); } } //this point shouldn't be reached abort(); return 0; } QString KMountManGUI::getMntPoint(QTreeWidgetItem *item) { return item->text(2); // text(2) ? ugly ugly ugly } KrMountDetector::KrMountDetector() { hasMountsChanged(); } bool KrMountDetector::hasMountsChanged() { bool result = false; #ifndef BSD QFileInfo mtabInfo(MTAB); if (!mtabInfo.exists() || mtabInfo.isSymLink()) { // if mtab is a symlimk to /proc/mounts the mtime is unusable #endif KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName); QCryptographicHash md5(QCryptographicHash::Md5); for (KMountPoint::List::iterator i = mountPoints.begin(); i != mountPoints.end(); ++i) { md5.addData((*i)->mountedFrom().toUtf8()); md5.addData((*i)->realDeviceName().toUtf8()); md5.addData((*i)->mountPoint().toUtf8()); md5.addData((*i)->mountType().toUtf8()); } QString s = md5.result(); result = s != checksum; checksum = s; #ifndef BSD } else { result = mtabInfo.lastModified() != lastMtab; lastMtab = mtabInfo.lastModified(); } #endif return result; } KrMountDetector krMountDetector; KrMountDetector * KrMountDetector::getInstance() { return & krMountDetector; } diff --git a/krusader/MountMan/kmountmangui.h b/krusader/MountMan/kmountmangui.h index f80b35d6..f26f98f3 100644 --- a/krusader/MountMan/kmountmangui.h +++ b/krusader/MountMan/kmountmangui.h @@ -1,203 +1,193 @@ -/*************************************************************************** - kmountmangui.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KMOUNTMANGUI_H #define KMOUNTMANGUI_H // QtCore #include #include #include // QtWidgets #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(); protected: virtual void resizeEvent(QResizeEvent *e) Q_DECL_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 = n_; } inline void setType(QString t_) { Type = t_; } inline void setMntPoint(QString m_) { MntPoint = 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/krview.cpp b/krusader/Panel/PanelView/krview.cpp index 132a1122..693a7a19 100644 --- a/krusader/Panel/PanelView/krview.cpp +++ b/krusader/Panel/PanelView/krview.cpp @@ -1,1233 +1,1224 @@ -/*************************************************************************** - krview.cpp - ------------------- - copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000-2002 Shie Erlich * + * Copyright (C) 2000-2002 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krview.h" #include "krselectionmode.h" #include "krviewfactory.h" #include "krviewitem.h" #include "../FileSystem/dirlisterinterface.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/krpermhandler.h" #include "../Filter/filterdialog.h" #include "../defaults.h" #include "../kicons.h" #include "../krcolorcache.h" #include "../krglobal.h" #include "../krpreviews.h" #include "../viewactions.h" // QtCore #include #include // QtGui #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #define FILEITEM getFileItem() KrView *KrViewOperator::_changedView = 0; KrViewProperties::PropertyType KrViewOperator::_changedProperties = KrViewProperties::NoProperty; // ----------------------------- operator KrViewOperator::KrViewOperator(KrView *view, QWidget *widget) : _view(view), _widget(widget), _massSelectionUpdate(false) { _saveDefaultSettingsTimer.setSingleShot(true); connect(&_saveDefaultSettingsTimer, SIGNAL(timeout()), SLOT(saveDefaultSettings())); } KrViewOperator::~KrViewOperator() { if(_changedView == _view) saveDefaultSettings(); } void KrViewOperator::startUpdate() { _view->refresh(); } void KrViewOperator::cleared() { _view->clear(); } void KrViewOperator::fileAdded(FileItem *fileitem) { _view->addItem(fileitem); } void KrViewOperator::fileUpdated(FileItem *newFileitem) { _view->updateItem(newFileitem); } void KrViewOperator::startDrag() { QStringList items; _view->getSelectedItems(&items); if (items.empty()) return ; // don't drag an empty thing QPixmap px; if (items.count() > 1 || _view->getCurrentKrViewItem() == 0) px = FL_LOADICON("queue"); // how much are we dragging else px = _view->getCurrentKrViewItem() ->icon(); emit letsDrag(items, px); } bool KrViewOperator::searchItem(const QString &text, bool caseSensitive, int direction) { KrViewItem * item = _view->getCurrentKrViewItem(); if (!item) { return false; } const QRegExp regeEx(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); if (!direction) { if (regeEx.indexIn(item->name()) == 0) { return true; } direction = 1; } KrViewItem * startItem = item; while (true) { item = (direction > 0) ? _view->getNext(item) : _view->getPrev(item); if (!item) item = (direction > 0) ? _view->getFirst() : _view->getLast(); if (regeEx.indexIn(item->name()) == 0) { _view->setCurrentKrViewItem(item); _view->makeItemVisible(item); return true; } if (item == startItem) { return false; } } } bool KrViewOperator::filterSearch(const QString &text, bool caseSensitive) { _view->_quickFilterMask = QRegExp(text, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); _view->refresh(); return _view->_count || !_view->_files->numFileItems(); } void KrViewOperator::setMassSelectionUpdate(bool upd) { _massSelectionUpdate = upd; if (!upd) { emit selectionChanged(); _view->redraw(); } } void KrViewOperator::settingsChanged(KrViewProperties::PropertyType properties) { if(!_view->_updateDefaultSettings || _view->_ignoreSettingsChange) return; if(_changedView != _view) saveDefaultSettings(); _changedView = _view; _changedProperties = static_cast(_changedProperties | properties); _saveDefaultSettingsTimer.start(100); } void KrViewOperator::saveDefaultSettings() { _saveDefaultSettingsTimer.stop(); if(_changedView) _changedView->saveDefaultSettings(_changedProperties); _changedProperties = KrViewProperties::NoProperty; _changedView = 0; } // ----------------------------- krview const KrView::IconSizes KrView::iconSizes; KrView::KrView(KrViewInstance &instance, KConfig *cfg) : _config(cfg), _properties(0), _focused(false), _fileIconSize(0), _instance(instance), _files(0), _mainWindow(0), _widget(0), _nameToMakeCurrent(QString()), _previews(0), _updateDefaultSettings(false), _ignoreSettingsChange(false), _count(0), _numDirs(0), _dummyFileItem(0) { } KrView::~KrView() { _instance.m_objects.removeOne(this); delete _previews; _previews = 0; delete _dummyFileItem; _dummyFileItem = 0; if (_properties) qFatal("A class inheriting KrView didn't delete _properties!"); if (_operator) qFatal("A class inheriting KrView didn't delete _operator!"); } void KrView::init(bool enableUpdateDefaultSettings) { // sanity checks: if (!_widget) qFatal("_widget must be set during construction of KrView inheritors"); // ok, continue initProperties(); _operator = createOperator(); setup(); restoreDefaultSettings(); _updateDefaultSettings = enableUpdateDefaultSettings && KConfigGroup(_config, "Startup").readEntry("Update Default Panel Settings", _RememberPos); _instance.m_objects.append(this); } void KrView::initProperties() { const KConfigGroup grpInstance(_config, _instance.name()); const bool displayIcons = grpInstance.readEntry("With Icons", _WithIcons); const KConfigGroup grpSvr(_config, "Look&Feel"); const bool numericPermissions = grpSvr.readEntry("Numeric permissions", _NumericPermissions); int sortOps = 0; if (grpSvr.readEntry("Show Directories First", true)) sortOps |= KrViewProperties::DirsFirst; if(grpSvr.readEntry("Always sort dirs by name", false)) sortOps |= KrViewProperties::AlwaysSortDirsByName; if (!grpSvr.readEntry("Case Sensative Sort", _CaseSensativeSort)) sortOps |= KrViewProperties::IgnoreCase; if (grpSvr.readEntry("Locale Aware Sort", true)) sortOps |= KrViewProperties::LocaleAwareSort; KrViewProperties::SortOptions sortOptions = static_cast(sortOps); KrViewProperties::SortMethod sortMethod = static_cast( grpSvr.readEntry("Sort method", (int)_DefaultSortMethod)); const bool humanReadableSize = grpSvr.readEntry("Human Readable Size", _HumanReadableSize); // see KDE bug #40131 const bool localeAwareCompareIsCaseSensitive = QString("a").localeAwareCompare("B") > 0; QStringList defaultAtomicExtensions; defaultAtomicExtensions += ".tar.gz"; defaultAtomicExtensions += ".tar.bz2"; defaultAtomicExtensions += ".tar.lzma"; defaultAtomicExtensions += ".tar.xz"; defaultAtomicExtensions += ".moc.cpp"; QStringList atomicExtensions = grpSvr.readEntry("Atomic Extensions", defaultAtomicExtensions); for (QStringList::iterator i = atomicExtensions.begin(); i != atomicExtensions.end();) { QString & ext = *i; ext = ext.trimmed(); if (!ext.length()) { i = atomicExtensions.erase(i); continue; } if (!ext.startsWith('.')) ext.insert(0, '.'); ++i; } _properties = new KrViewProperties(displayIcons, numericPermissions, sortOptions, sortMethod, humanReadableSize, localeAwareCompareIsCaseSensitive, atomicExtensions); } void KrView::showPreviews(bool show) { if(show) { if(!_previews) { _previews = new KrPreviews(this); _previews->update(); } } else { delete _previews; _previews = 0; } redraw(); // op()->settingsChanged(KrViewProperties::PropShowPreviews); op()->emitRefreshActions(); } void KrView::updatePreviews() { if(_previews) _previews->update(); } QPixmap KrView::processIcon(const QPixmap &icon, bool dim, const QColor & dimColor, int dimFactor, bool symlink) { QPixmap pixmap = icon; if (symlink) { const QStringList overlays = QStringList() << QString() << "emblem-symbolic-link"; KIconLoader::global()->drawOverlays(overlays, pixmap, KIconLoader::Desktop); } if(!dim) return pixmap; QImage dimmed = pixmap.toImage(); QPainter p(&dimmed); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(0, 0, icon.width(), icon.height(), dimColor); p.setCompositionMode(QPainter::CompositionMode_SourceOver); p.setOpacity((qreal)dimFactor / (qreal)100); p.drawPixmap(0, 0, icon.width(), icon.height(), pixmap); return QPixmap::fromImage(dimmed, Qt::ColorOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection ); } QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size/*, KRListItem::cmpColor color*/) { // KConfigGroup ag( krConfig, "Advanced"); ////////////////////////////// QPixmap icon; QString icon_name = fileitem->getIcon(); QString cacheName; if(!size) size = _FilelistIconSize.toInt(); QColor dimColor; int dimFactor; bool dim = !active && KrColorCache::getColorCache().getDimSettings(dimColor, dimFactor); if (icon_name.isNull()) icon_name = ""; cacheName.append(QString::number(size)); if(fileitem->isSymLink()) cacheName.append("LINK_"); if(dim) cacheName.append("DIM_"); cacheName.append(icon_name); //QPixmapCache::setCacheLimit( ag.readEntry("Icon Cache Size",_IconCacheSize) ); // first try the cache if (!QPixmapCache::find(cacheName, icon)) { icon = processIcon(krLoader->loadIcon(icon_name, KIconLoader::Desktop, size), dim, dimColor, dimFactor, fileitem->isSymLink()); // insert it into the cache QPixmapCache::insert(cacheName, icon); } return icon; } QPixmap KrView::getIcon(FileItem *fileitem) { if(_previews) { QPixmap icon; if(_previews->getPreview(fileitem, icon, _focused)) return icon; } return getIcon(fileitem, _focused, _fileIconSize); } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getItemsByMask(QString mask, QStringList* names, bool dirs, bool files) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if ((it->name() == "..") || !QDir::match(mask, it->name())) continue; // if we got here, than the item fits the mask if (it->getFileItem()->isDir() && !dirs) continue; // do we need to skip folders? if (!it->getFileItem()->isDir() && !files) continue; // do we need to skip files names->append(it->name()); } } /** * this function ADDs a list of selected item names into 'names'. * it assumes the list is ready and doesn't initialize it, or clears it */ void KrView::getSelectedItems(QStringList *names, bool fallbackToFocused) { for (KrViewItem *it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) names->append(it->name()); if (fallbackToFocused) { // if all else fails, take the current item const QString item = getCurrentItem(); if (names->empty() && !item.isEmpty() && item != "..") { names->append(item); } } } void KrView::getSelectedKrViewItems(KrViewItemList *items) { for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) if (it->isSelected() && (it->name() != "..")) items->append(it); // if all else fails, take the current item QString item = getCurrentItem(); if (items->empty() && !item.isEmpty() && item != ".." && getCurrentKrViewItem() != 0) { items->append(getCurrentKrViewItem()); } } QString KrView::statistics() { KIO::filesize_t size = calcSize(); KIO::filesize_t selectedSize = calcSelectedSize(); QString tmp; KConfigGroup grp(_config, "Look&Feel"); if(grp.readEntry("Show Size In Bytes", false)) { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize in Bytes, \ %5=filesize of all items in folder,%6=filesize in Bytes", "%1 out of %2, %3 (%4) out of %5 (%6)", numSelected(), _count, KIO::convertSize(selectedSize), KRpermHandler::parseSize(selectedSize), KIO::convertSize(size), KRpermHandler::parseSize(size)); } else { tmp = i18nc("%1=number of selected items,%2=total number of items, \ %3=filesize of selected items,%4=filesize of all items in folder", "%1 out of %2, %3 out of %4", numSelected(), _count, KIO::convertSize(selectedSize), KIO::convertSize(size)); } // notify if we're running a filtered view if (filter() != KrViewProperties::All) tmp = ">> [ " + filterMask().nameFilter() + " ] " + tmp; return tmp; } bool KrView::changeSelection(const KRQuery& filter, bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); return changeSelection(filter, select, grpSvr.readEntry("Mark Dirs", _MarkDirs), true); } bool KrView::changeSelection(const KRQuery& filter, bool select, bool includeDirs, bool makeVisible) { if (op()) op()->setMassSelectionUpdate(true); KrViewItem *temp = getCurrentKrViewItem(); KrViewItem *firstMatch = 0; for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getFileItem()->isDir() && !includeDirs) continue; FileItem * file = it->getMutableFileItem(); // filter::match calls getMimetype which isn't const if (file == 0) continue; if (filter.match(file)) { it->setSelected(select); if (!firstMatch) firstMatch = it; } } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) { makeItemVisible(temp); } else if (makeVisible && firstMatch != 0) { // if no selected item is visible... KrViewItemList selectedItems; getSelectedKrViewItems(&selectedItems); bool anyVisible = false; for (KrViewItem *item : selectedItems) { if (isItemVisible(item)) { anyVisible = true; break; } } if (!anyVisible) { // ...scroll to fist selected item makeItemVisible(firstMatch); } } redraw(); return firstMatch != 0; // return if any file was selected } void KrView::invertSelection() { if (op()) op()->setMassSelectionUpdate(true); KConfigGroup grpSvr(_config, "Look&Feel"); bool markDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); KrViewItem *temp = getCurrentKrViewItem(); for (KrViewItem * it = getFirst(); it != 0; it = getNext(it)) { if (it->name() == "..") continue; if (it->getFileItem()->isDir() && !markDirs && !it->isSelected()) continue; it->setSelected(!it->isSelected()); } if (op()) op()->setMassSelectionUpdate(false); updateView(); if (ensureVisibilityAfterSelect() && temp != 0) makeItemVisible(temp); } QString KrView::firstUnmarkedBelowCurrent(const bool skipCurrent) { if (getCurrentKrViewItem() == 0) return QString(); KrViewItem *iterator = getCurrentKrViewItem(); if (skipCurrent) iterator = getNext(iterator); while (iterator && iterator->isSelected()) iterator = getNext(iterator); if (!iterator) { iterator = getPrev(getCurrentKrViewItem()); while (iterator && iterator->isSelected()) iterator = getPrev(iterator); } if (!iterator) return QString(); return iterator->name(); } void KrView::delItem(const QString &name) { KrViewItem *it = findItemByName(name); if(!it) return; if(_previews) _previews->deletePreview(it); preDelItem(it); if (it->FILEITEM->isDir()) { --_numDirs; } --_count; delete it; op()->emitSelectionChanged(); } void KrView::addItem(FileItem *fileitem) { if (isFiltered(fileitem)) return; KrViewItem *item = preAddItem(fileitem); if (!item) return; // don't add it after all if(_previews) _previews->updatePreview(item); if (fileitem->isDir()) ++_numDirs; ++_count; if (item->name() == nameToMakeCurrent()) { setCurrentKrViewItem(item); // dictionary based - quick makeItemVisible(item); } op()->emitSelectionChanged(); } void KrView::updateItem(FileItem *newFileItem) { // file name did not change const QString name = newFileItem->getName(); // preserve 'current' and 'selection' const bool isCurrent = getCurrentItem() == name; QStringList selectedNames; getSelectedItems(&selectedNames, false); const bool isSelected = selectedNames.contains(name); // delete old file item delItem(name); if (!isFiltered(newFileItem)) { addItem(newFileItem); if(_previews) _previews->updatePreview(findItemByFileItem(newFileItem)); } if (isCurrent) setCurrentItem(name); if (isSelected) setSelected(newFileItem, true); op()->emitSelectionChanged(); } void KrView::clear() { if(_previews) _previews->clear(); _count = _numDirs = 0; delete _dummyFileItem; _dummyFileItem = 0; redraw(); } bool KrView::handleKeyEvent(QKeyEvent *e) { qDebug() << "key event=" << e; switch (e->key()) { case Qt::Key_Enter : case Qt::Key_Return : { if (e->modifiers() & Qt::ControlModifier) // let the panel handle it e->ignore(); else { KrViewItem * i = getCurrentKrViewItem(); if (i == 0) return true; QString tmp = i->name(); op()->emitExecuted(tmp); } return true; } case Qt::Key_QuoteLeft : // Terminal Emulator bugfix if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing // ask krusader to move to the home directory op()->emitGoHome(); } return true; case Qt::Key_Delete : // delete/trash the file (delete with alternative mode is a panel action) // allow only no modifier or KeypadModifier (i.e. Del on a Numeric Keypad) if ((e->modifiers() & ~Qt::KeypadModifier) == Qt::NoModifier) { op()->emitDefaultDeleteFiles(); } return true; case Qt::Key_Insert: { KrViewItem * i = getCurrentKrViewItem(); if (!i) return true; i->setSelected(!i->isSelected()); if (KrSelectionMode::getSelectionHandler()->insertMovesDown()) { KrViewItem * next = getNext(i); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); return true; } case Qt::Key_Space: { KrViewItem * viewItem = getCurrentKrViewItem(); if (viewItem != 0) { viewItem->setSelected(!viewItem->isSelected()); if (viewItem->getFileItem()->isDir() && KrSelectionMode::getSelectionHandler()->spaceCalculatesDiskSpace()) { op()->emitQuickCalcSpace(viewItem); } if (KrSelectionMode::getSelectionHandler()->spaceMovesDown()) { KrViewItem * next = getNext(viewItem); if (next) { setCurrentKrViewItem(next); makeItemVisible(next); } } op()->emitSelectionChanged(); } return true; } case Qt::Key_Backspace : // Terminal Emulator bugfix case Qt::Key_Left : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // a normal click - do a lynx-like moving thing // ask krusader to move up a directory op()->emitDirUp(); } return true; // safety case Qt::Key_Right : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == Qt::ShiftModifier || e->modifiers() == Qt::AltModifier) { // let the panel handle it e->ignore(); } else { // just a normal click - do a lynx-like moving thing KrViewItem *i = getCurrentKrViewItem(); if (i) op()->emitGoInside(i->name()); } return true; case Qt::Key_Up : if (e->modifiers() == Qt::ControlModifier) { // let the panel handle it - jump to the Location Bar e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getPrev(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Down : if (e->modifiers() == Qt::ControlModifier || e->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) { // let the panel handle it - jump to command line e->ignore(); } else { KrViewItem *item = getCurrentKrViewItem(); if (item) { if (e->modifiers() == Qt::ShiftModifier) { item->setSelected(!item->isSelected()); op()->emitSelectionChanged(); } item = getNext(item); if (item) { setCurrentKrViewItem(item); makeItemVisible(item); } } } return true; case Qt::Key_Home: { if (e->modifiers() & Qt::ShiftModifier) { bool select = true; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getLast(); KrViewItem *item = getFirst(); op()->setMassSelectionUpdate(true); while (item) { item->setSelected(select); if (item == pos) select = false; item = getNext(item); } op()->setMassSelectionUpdate(false); } KrViewItem * first = getFirst(); if (first) { setCurrentKrViewItem(first); makeItemVisible(first); } } return true; case Qt::Key_End: if (e->modifiers() & Qt::ShiftModifier) { bool select = false; KrViewItem *pos = getCurrentKrViewItem(); if (pos == 0) pos = getFirst(); op()->setMassSelectionUpdate(true); KrViewItem *item = getFirst(); while (item) { if (item == pos) select = true; item->setSelected(select); item = getNext(item); } op()->setMassSelectionUpdate(false); } else { KrViewItem *last = getLast(); if (last) { setCurrentKrViewItem(last); makeItemVisible(last); } } return true; case Qt::Key_PageDown: { KrViewItem * current = getCurrentKrViewItem(); int downStep = itemsPerPage(); while (downStep != 0 && current) { KrViewItem * newCurrent = getNext(current); if (newCurrent == 0) break; current = newCurrent; downStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_PageUp: { KrViewItem * current = getCurrentKrViewItem(); int upStep = itemsPerPage(); while (upStep != 0 && current) { KrViewItem * newCurrent = getPrev(current); if (newCurrent == 0) break; current = newCurrent; upStep--; } if (current) { setCurrentKrViewItem(current); makeItemVisible(current); } return true; } case Qt::Key_Escape: e->ignore(); return true; // otherwise the selection gets lost??!?? // also it is needed by the panel case Qt::Key_A : // mark all if (e->modifiers() == Qt::ControlModifier) { //FIXME: shouldn't there also be a shortcut for unselecting everything ? selectAllIncludingDirs(); return true; } #if __GNUC__ >= 7 [[gnu::fallthrough]]; #endif default: return false; } return false; } void KrView::zoomIn() { int idx = iconSizes.indexOf(_fileIconSize); if(idx >= 0 && (idx+1) < iconSizes.count()) setFileIconSize(iconSizes[idx+1]); } void KrView::zoomOut() { int idx = iconSizes.indexOf(_fileIconSize); if(idx > 0) setFileIconSize(iconSizes[idx-1]); } void KrView::setFileIconSize(int size) { if(iconSizes.indexOf(size) < 0) return; _fileIconSize = size; if(_previews) { _previews->clear(); _previews->update(); } redraw(); op()->emitRefreshActions(); } int KrView::defaultFileIconSize() { KConfigGroup grpSvr(_config, _instance.name()); return grpSvr.readEntry("IconSize", _FilelistIconSize).toInt(); } void KrView::saveDefaultSettings(KrViewProperties::PropertyType properties) { saveSettings(KConfigGroup(_config, _instance.name()), properties); op()->emitRefreshActions(); } void KrView::restoreDefaultSettings() { restoreSettings(KConfigGroup(_config, _instance.name())); } void KrView::saveSettings(KConfigGroup group, KrViewProperties::PropertyType properties) { if(properties & KrViewProperties::PropIconSize) group.writeEntry("IconSize", fileIconSize()); if(properties & KrViewProperties::PropShowPreviews) group.writeEntry("ShowPreviews", previewsShown()); if(properties & KrViewProperties::PropSortMode) saveSortMode(group); if(properties & KrViewProperties::PropFilter) { group.writeEntry("Filter", static_cast(_properties->filter)); group.writeEntry("FilterApplysToDirs", _properties->filterApplysToDirs); if(_properties->filterSettings.isValid()) _properties->filterSettings.save(KConfigGroup(&group, "FilterSettings")); } } void KrView::restoreSettings(KConfigGroup group) { _ignoreSettingsChange = true; doRestoreSettings(group); _ignoreSettingsChange = false; refresh(); } void KrView::doRestoreSettings(KConfigGroup group) { restoreSortMode(group); setFileIconSize(group.readEntry("IconSize", defaultFileIconSize())); showPreviews(group.readEntry("ShowPreviews", false)); _properties->filter = static_cast(group.readEntry("Filter", static_cast(KrViewProperties::All))); _properties->filterApplysToDirs = group.readEntry("FilterApplysToDirs", false); _properties->filterSettings.load(KConfigGroup(&group, "FilterSettings")); _properties->filterMask = _properties->filterSettings.toQuery(); } void KrView::applySettingsToOthers() { for(int i = 0; i < _instance.m_objects.length(); i++) { KrView *view = _instance.m_objects[i]; if(this != view) { view->_ignoreSettingsChange = true; view->copySettingsFrom(this); view->_ignoreSettingsChange = false; } } } void KrView::sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending) { if(sortColumn == _properties->sortColumn && descending == (bool) (_properties->sortOptions & KrViewProperties::Descending)) return; int options = _properties->sortOptions; if(descending) options |= KrViewProperties::Descending; else options &= ~KrViewProperties::Descending; _properties->sortColumn = sortColumn; _properties->sortOptions = static_cast(options); // op()->settingsChanged(KrViewProperties::PropSortMode); } bool KrView::drawCurrent() const { return isFocused() || KConfigGroup(_config, "Look&Feel") .readEntry("Always Show Current Item", _AlwaysShowCurrentItem); } void KrView::saveSortMode(KConfigGroup &group) { group.writeEntry("Sort Column", static_cast(_properties->sortColumn)); group.writeEntry("Descending Sort Order", _properties->sortOptions & KrViewProperties::Descending); } void KrView::restoreSortMode(KConfigGroup &group) { int column = group.readEntry("Sort Column", static_cast(KrViewProperties::Name)); bool isDescending = group.readEntry("Descending Sort Order", false); setSortMode(static_cast(column), isDescending); } QString KrView::krPermissionText(const FileItem * fileitem) { QString tmp; switch (fileitem->isReadable()) { case ALLOWED_PERM: tmp+='r'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (fileitem->isWriteable()) { case ALLOWED_PERM: tmp+='w'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } switch (fileitem->isExecutable()) { case ALLOWED_PERM: tmp+='x'; break; case UNKNOWN_PERM: tmp+='?'; break; case NO_PERM: tmp+='-'; break; } return tmp; } QString KrView::permissionsText(const KrViewProperties *properties, const FileItem *fileItem) { return properties->numericPermissions ? QString().asprintf("%.4o", fileItem->getMode() & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)) : fileItem->getPerm(); } QString KrView::sizeText(const KrViewProperties *properties, KIO::filesize_t size) { return properties->humanReadableSize ? KIO::convertSize(size) : KRpermHandler::parseSize(size); } QString KrView::mimeTypeText(FileItem *fileItem) { QMimeType mt = QMimeDatabase().mimeTypeForName(fileItem->getMime()); return mt.isValid() ? mt.comment() : QString(); } bool KrView::isFiltered(FileItem *fileitem) { if (_quickFilterMask.isValid() && _quickFilterMask.indexIn(fileitem->getName()) == -1) return true; bool filteredOut = false; bool isDir = fileitem->isDir(); if (!isDir || (isDir && properties()->filterApplysToDirs)) { switch (properties()->filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : if (!properties()->filterMask.match(fileitem)) filteredOut = true; break; case KrViewProperties::Dirs: if (!isDir) filteredOut = true; break; case KrViewProperties::Files: if (isDir) filteredOut = true; break; default: break; } } return filteredOut; } void KrView::setFiles(DirListerInterface *files) { if(files != _files) { clear(); if(_files) QObject::disconnect(_files, 0, op(), 0); _files = files; } if(!_files) return; QObject::disconnect(_files, 0, op(), 0); QObject::connect(_files, &DirListerInterface::scanDone, op(), &KrViewOperator::startUpdate); QObject::connect(_files, &DirListerInterface::cleared, op(), &KrViewOperator::cleared); QObject::connect(_files, &DirListerInterface::addedFileItem, op(), &KrViewOperator::fileAdded); QObject::connect(_files, &DirListerInterface::updatedFileItem, op(), &KrViewOperator::fileUpdated); } void KrView::setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter, bool applyToDirs) { _properties->filter = filter; _properties->filterSettings = customFilter; _properties->filterMask = customFilter.toQuery(); _properties->filterApplysToDirs = applyToDirs; refresh(); } void KrView::setFilter(KrViewProperties::FilterSpec filter) { KConfigGroup cfg(_config, "Look&Feel"); bool rememberSettings = cfg.readEntry("FilterDialogRemembersSettings", _FilterDialogRemembersSettings); bool applyToDirs = rememberSettings ? _properties->filterApplysToDirs : false; switch (filter) { case KrViewProperties::All : break; case KrViewProperties::Custom : { FilterDialog dialog(_widget, i18n("Filter Files"), QStringList(i18n("Apply filter to folders")), false); dialog.checkExtraOption(i18n("Apply filter to folders"), applyToDirs); if(rememberSettings) dialog.applySettings(_properties->filterSettings); dialog.exec(); FilterSettings s(dialog.getSettings()); if(!s.isValid()) // if the user canceled - quit return; _properties->filterSettings = s; _properties->filterMask = s.toQuery(); applyToDirs = dialog.isExtraOptionChecked(i18n("Apply filter to folders")); } break; default: return; } _properties->filterApplysToDirs = applyToDirs; _properties->filter = filter; refresh(); } void KrView::customSelection(bool select) { KConfigGroup grpSvr(_config, "Look&Feel"); bool includeDirs = grpSvr.readEntry("Mark Dirs", _MarkDirs); FilterDialog dialog(0, i18n("Select Files"), QStringList(i18n("Apply selection to folders")), false); dialog.checkExtraOption(i18n("Apply selection to folders"), includeDirs); dialog.exec(); KRQuery query = dialog.getQuery(); // if the user canceled - quit if (query.isNull()) return; includeDirs = dialog.isExtraOptionChecked(i18n("Apply selection to folders")); changeSelection(query, select, includeDirs); } void KrView::refresh() { QString currentItem = getCurrentItem(); QList selection = selectedUrls(); QModelIndex currentIndex = getCurrentIndex(); clear(); if(!_files) return; QList fileItems; // if we are not at the root add the ".." entry if(!_files->isRoot()) { _dummyFileItem = FileItem::createDummy(); fileItems << _dummyFileItem; } foreach(FileItem *fileitem, _files->fileItems()) { if(!fileitem || isFiltered(fileitem)) continue; if(fileitem->isDir()) _numDirs++; _count++; fileItems << fileitem; } populate(fileItems, _dummyFileItem); if(!selection.isEmpty()) setSelectionUrls(selection); if (!nameToMakeCurrent().isEmpty()) { setCurrentItem(nameToMakeCurrent()); setNameToMakeCurrent(""); } else if (!currentItem.isEmpty()) { if (currentItem == ".." && _count > 0 && !_quickFilterMask.isEmpty() && _quickFilterMask.isValid()) { // In a filtered view we should never select the dummy entry if // there are real matches. setCurrentKrViewItem(getNext(getFirst())); } else setCurrentItem(currentItem, currentIndex); } else { setCurrentKrViewItem(getFirst()); } updatePreviews(); redraw(); op()->emitSelectionChanged(); } void KrView::setSelected(const FileItem* fileitem, bool select) { if (fileitem == _dummyFileItem) return; if (select) clearSavedSelection(); intSetSelected(fileitem, select); } void KrView::saveSelection() { _savedSelection = selectedUrls(); op()->emitRefreshActions(); } void KrView::restoreSelection() { if(canRestoreSelection()) setSelectionUrls(_savedSelection); } void KrView::clearSavedSelection() { _savedSelection.clear(); op()->emitRefreshActions(); } void KrView::markSameBaseName() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("%1.*").arg(item->name(false))); changeSelection(query, true, false); } void KrView::markSameExtension() { KrViewItem* item = getCurrentKrViewItem(); if (!item) return; KRQuery query(QString("*.%1").arg(item->extension())); changeSelection(query, true, false); } diff --git a/krusader/Panel/PanelView/krview.h b/krusader/Panel/PanelView/krview.h index b72c41f4..7dd7f533 100644 --- a/krusader/Panel/PanelView/krview.h +++ b/krusader/Panel/PanelView/krview.h @@ -1,384 +1,376 @@ -/*************************************************************************** - krview.h - ------------------- - copyright : (C) 2000-2002 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000-2002 Shie Erlich * + * Copyright (C) 2000-2002 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ + #ifndef KRVIEW_H #define KRVIEW_H // QtCore #include #include #include #include #include #include // QtGui #include #include #include "krviewproperties.h" class KrView; class KrViewItem; class KrPreviews; class KrViewInstance; class DirListerInterface; typedef QList KrViewItemList; // operator can handle two ways of doing things: // 1. if the view is a widget (inherits krview and klistview for example) // 2. if the view HAS A widget (a krview-son has a member of klistview) // this is done by specifying the view and the widget in the constructor, // even if they are actually the same object (specify it twice in that case) class KrViewOperator : public QObject { Q_OBJECT public: KrViewOperator(KrView *view, QWidget *widget); ~KrViewOperator(); KrView *view() const { return _view; } QWidget *widget() const { return _widget; } void startDrag(); void emitGotDrop(QDropEvent *e) { emit gotDrop(e); } void emitLetsDrag(QStringList items, QPixmap icon) { emit letsDrag(items, icon); } void emitItemDescription(const QString &desc) { emit itemDescription(desc); } void emitContextMenu(const QPoint &point) { emit contextMenu(point); } void emitEmptyContextMenu(const QPoint &point) { emit emptyContextMenu(point); } void emitRenameItem(const QString &oldName, const QString &newName) { emit renameItem(oldName, newName); } void emitExecuted(const QString &name) { emit executed(name); } void emitGoInside(const QString &name) { emit goInside(name); } void emitNeedFocus() { emit needFocus(); } void emitMiddleButtonClicked(KrViewItem *item) { emit middleButtonClicked(item); } void emitCurrentChanged(KrViewItem *item) { emit currentChanged(item); } void emitPreviewJobStarted(KJob *job) { emit previewJobStarted(job); } void emitGoHome() { emit goHome(); } void emitDirUp() { emit dirUp(); } void emitQuickCalcSpace(KrViewItem *item) { emit quickCalcSpace(item); } void emitDefaultDeleteFiles() { emit defaultDeleteFiles(); } void emitRefreshActions() { emit refreshActions(); } void emitGoBack() { emit goBack(); } void emitGoForward() { emit goForward(); } /** * Search for an item by file name beginning at the current cursor position and set the * cursor to it. * * @param text file name to search for, can be regex * @return true if there is a next/previous item matching the text, else false */ bool searchItem(const QString &text, bool caseSensitive, int direction = 0); /** * Filter view items. */ bool filterSearch(const QString &, bool); void setMassSelectionUpdate(bool upd); bool isMassSelectionUpdate() { return _massSelectionUpdate; } void settingsChanged(KrViewProperties::PropertyType properties); public slots: void emitSelectionChanged() { if (!_massSelectionUpdate) emit selectionChanged(); } void startUpdate(); void cleared(); void fileAdded(FileItem *fileitem); void fileUpdated(FileItem *newFileitem); signals: void selectionChanged(); void gotDrop(QDropEvent *e); void letsDrag(QStringList items, QPixmap icon); void itemDescription(const QString &desc); void contextMenu(const QPoint &point); void emptyContextMenu(const QPoint &point); void renameItem(const QString &oldName, const QString &newName); void executed(const QString &name); void goInside(const QString &name); void needFocus(); void middleButtonClicked(KrViewItem *item); void currentChanged(KrViewItem *item); void previewJobStarted(KJob *job); void goHome(); void defaultDeleteFiles(); void dirUp(); void quickCalcSpace(KrViewItem *item); void refreshActions(); void goBack(); void goForward(); protected slots: void saveDefaultSettings(); protected: // never delete those KrView *_view; QWidget *_widget; private: bool _massSelectionUpdate; QTimer _saveDefaultSettingsTimer; static KrViewProperties::PropertyType _changedProperties; static KrView *_changedView; }; /**************************************************************************** * READ THIS FIRST: Using the view * * You always hold a pointer to KrView, thus you can only use functions declared * in this class. If you need something else, either this class is missing something * or you are ;-) * * The functions you'd usually want: * 1) getSelectedItems - returns all selected items, or (if none) the current item. * it never returns anything which includes the "..", and thus can return an empty list! * 2) getSelectedKrViewItems - the same as (1), but returns a QValueList with KrViewItems * 3) getCurrentItem, setCurrentItem - work with QString * 4) getFirst, getNext, getPrev, getCurrentKrViewItem - all work with KrViewItems, and * used to iterate through a list of items. note that getNext and getPrev accept a pointer * to the current item (used in detailedview for safe iterating), thus your loop should be: * for (KrViewItem *it = view->getFirst(); it!=0; it = view->getNext(it)) { blah; } * 5) nameToMakeCurrent(), setNameToMakeCurrent() - work with QString * * IMPORTANT NOTE: every one who subclasses this must call initProperties() in the constructor !!! */ class KrView { friend class KrViewItem; friend class KrViewOperator; public: class IconSizes : public QVector { public: IconSizes() : QVector() { *this << 12 << 16 << 22 << 32 << 48 << 64 << 128 << 256; } }; // instantiating a new view // 1. new KrView // 2. view->init() // notes: constructor does as little as possible, setup() does the rest. esp, note that // if you need something from operator or properties, move it into setup() void init(bool enableUpdateDefaultSettings = true); KrViewInstance *instance() { return &_instance; } static const IconSizes iconSizes; protected: void initProperties(); KrViewOperator *createOperator() { return new KrViewOperator(this, _widget); } virtual void setup() = 0; /////////////////////////////////////////////////////// // Every view must implement the following functions // /////////////////////////////////////////////////////// public: // interview related functions virtual QModelIndex getCurrentIndex() = 0; virtual bool isSelected(const QModelIndex &) = 0; virtual bool ensureVisibilityAfterSelect() = 0; virtual void selectRegion(KrViewItem *, KrViewItem *, bool) = 0; virtual uint numSelected() const = 0; virtual QList selectedUrls() = 0; virtual void setSelectionUrls(const QList urls) = 0; virtual KrViewItem *getFirst() = 0; virtual KrViewItem *getLast() = 0; virtual KrViewItem *getNext(KrViewItem *current) = 0; virtual KrViewItem *getPrev(KrViewItem *current) = 0; virtual KrViewItem *getCurrentKrViewItem() = 0; virtual KrViewItem *getKrViewItemAt(const QPoint &vp) = 0; virtual KrViewItem *findItemByName(const QString &name) = 0; virtual KrViewItem *findItemByFileItem(FileItem *vf) = 0; virtual KrViewItem *findItemByUrl(const QUrl &url) = 0; virtual QString getCurrentItem() const = 0; virtual void setCurrentItem(const QString &name, const QModelIndex &fallbackToIndex = QModelIndex()) = 0; virtual void setCurrentKrViewItem(KrViewItem *item) = 0; virtual void makeItemVisible(const KrViewItem *item) = 0; virtual bool isItemVisible(const KrViewItem *item) = 0; virtual void updateView() = 0; virtual void sort() = 0; virtual void refreshColors() = 0; virtual void redraw() = 0; virtual bool handleKeyEvent(QKeyEvent *e); virtual void prepareForActive() = 0; virtual void prepareForPassive() = 0; virtual void renameCurrentItem() = 0; // Rename current item. returns immediately virtual int itemsPerPage() = 0; virtual void showContextMenu(const QPoint &point = QPoint(0, 0)) = 0; protected: virtual KrViewItem *preAddItem(FileItem *fileitem) = 0; virtual void preDelItem(KrViewItem *item) = 0; virtual void copySettingsFrom(KrView *other) = 0; virtual void populate(const QList &fileItems, FileItem *dummy) = 0; virtual void intSetSelected(const FileItem *fileitem, bool select) = 0; virtual void clear(); void addItem(FileItem *fileitem); void updateItem(FileItem *newFileItem); void delItem(const QString &name); public: ////////////////////////////////////////////////////// // the following functions are already implemented, // // and normally - should NOT be re-implemented. // ////////////////////////////////////////////////////// uint numFiles() const { return _count - _numDirs; } uint numDirs() const { return _numDirs; } uint count() const { return _count; } void getSelectedItems(QStringList *names, bool fallbackToFocused = true); void getItemsByMask(QString mask, QStringList *names, bool dirs = true, bool files = true); void getSelectedKrViewItems(KrViewItemList *items); void selectAllIncludingDirs() { changeSelection(KRQuery("*"), true, true); } void select(const KRQuery &filter = KRQuery("*")) { changeSelection(filter, true); } void unselect(const KRQuery &filter = KRQuery("*")) { changeSelection(filter, false); } void unselectAll() { changeSelection(KRQuery("*"), false, true); } void invertSelection(); QString nameToMakeCurrent() const { return _nameToMakeCurrent; } void setNameToMakeCurrent(const QString name) { _nameToMakeCurrent = name; } QString firstUnmarkedBelowCurrent(const bool skipCurrent); QString statistics(); const KrViewProperties *properties() const { return _properties; } KrViewOperator *op() const { return _operator; } void showPreviews(bool show); bool previewsShown() { return _previews != 0; } void applySettingsToOthers(); void setFiles(DirListerInterface *files); void refresh(); bool changeSelection(const KRQuery &filter, bool select); bool changeSelection(const KRQuery &filter, bool select, bool includeDirs, bool makeVisible = false); bool isFiltered(FileItem *fileitem); void setSelected(const FileItem *fileitem, bool select); ///////////////////////////////////////////////////////////// // the following functions have a default and minimalistic // // implementation, and may be re-implemented if needed // ///////////////////////////////////////////////////////////// virtual void setSortMode(KrViewProperties::ColumnType sortColumn, bool descending) { sortModeUpdated(sortColumn, descending); } const KRQuery &filterMask() const { return _properties->filterMask; } KrViewProperties::FilterSpec filter() const { return _properties->filter; } void setFilter(KrViewProperties::FilterSpec filter); void setFilter(KrViewProperties::FilterSpec filter, FilterSettings customFilter, bool applyToDirs); void customSelection(bool select); int defaultFileIconSize(); virtual void setFileIconSize(int size); void setDefaultFileIconSize() { setFileIconSize(defaultFileIconSize()); } void zoomIn(); void zoomOut(); // save this view's settings to be restored after restart virtual void saveSettings(KConfigGroup grp, KrViewProperties::PropertyType properties = KrViewProperties::AllProperties); inline QWidget *widget() { return _widget; } inline int fileIconSize() const { return _fileIconSize; } inline bool isFocused() const { return _focused; } QPixmap getIcon(FileItem *fileitem); void setMainWindow(QWidget *mainWindow) { _mainWindow = mainWindow; } // save this view's settings as default for new views of this type void saveDefaultSettings( KrViewProperties::PropertyType properties = KrViewProperties::AllProperties); // restore the default settings for this view type void restoreDefaultSettings(); // call this to restore this view's settings after restart void restoreSettings(KConfigGroup grp); void saveSelection(); void restoreSelection(); bool canRestoreSelection() { return !_savedSelection.isEmpty(); } void clearSavedSelection(); void markSameBaseName(); void markSameExtension(); // todo: what about selection modes ??? virtual ~KrView(); static QPixmap getIcon(FileItem *fileitem, bool active, int size = 0); static QPixmap processIcon(const QPixmap &icon, bool dim, const QColor &dimColor, int dimFactor, bool symlink); // Get GUI strings for file item properties static QString krPermissionText(const FileItem *fileitem); static QString permissionsText(const KrViewProperties *properties, const FileItem *fileItem); static QString sizeText(const KrViewProperties *properties, KIO::filesize_t size); static QString mimeTypeText(FileItem *fileItem); protected: KrView(KrViewInstance &instance, KConfig *cfg); virtual void doRestoreSettings(KConfigGroup grp); virtual KIO::filesize_t calcSize() = 0; virtual KIO::filesize_t calcSelectedSize() = 0; void sortModeUpdated(KrViewProperties::ColumnType sortColumn, bool descending); inline void setWidget(QWidget *w) { _widget = w; } bool drawCurrent() const; KConfig *_config; KrViewProperties *_properties; KrViewOperator *_operator; bool _focused; int _fileIconSize; private: void updatePreviews(); void saveSortMode(KConfigGroup &group); void restoreSortMode(KConfigGroup &group); KrViewInstance &_instance; DirListerInterface *_files; QWidget *_mainWindow; QWidget *_widget; QList _savedSelection; QString _nameToMakeCurrent; KrPreviews *_previews; bool _updateDefaultSettings; bool _ignoreSettingsChange; QRegExp _quickFilterMask; uint _count, _numDirs; FileItem *_dummyFileItem; }; #endif /* KRVIEW_H */ diff --git a/krusader/Panel/PanelView/krviewfactory.cpp b/krusader/Panel/PanelView/krviewfactory.cpp index d4e955c2..1756e8c2 100644 --- a/krusader/Panel/PanelView/krviewfactory.cpp +++ b/krusader/Panel/PanelView/krviewfactory.cpp @@ -1,115 +1,107 @@ -/*************************************************************************** - krviewfactory.cpp - ------------------- -copyright : (C) 2000-2007 by Shie Erlich & Rafi Yanai & Csaba Karai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000-2007 Shie Erlich * + * Copyright (C) 2000-2007 Rafi Yanai * + * Copyright (C) 2000-2007 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krviewfactory.h" #include "krinterdetailedview.h" #include "krinterbriefview.h" #include #include KrViewInstance::KrViewInstance(int id, const QString &name, const QString &desc, const QString &icon, const QKeySequence &shortcut) : m_id(id), m_name(name), m_description(desc), m_icon(icon), 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) {} virtual KrView *create(QWidget *w, KConfig *cfg) Q_DECL_OVERRIDE { return new T(w, *this, cfg); } }; KrViewFactory::KrViewFactory() : m_defaultViewId(-1) {} // static initialization, on first use idiom KrViewFactory &KrViewFactory::self() { static KrViewFactory *factory = 0; 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/krviewfactory.h b/krusader/Panel/PanelView/krviewfactory.h index 1ef9d830..2b2b745e 100644 --- a/krusader/Panel/PanelView/krviewfactory.h +++ b/krusader/Panel/PanelView/krviewfactory.h @@ -1,96 +1,86 @@ -/*************************************************************************** - krviewfactory.h - ------------------- -copyright : (C) 2000-2008 by Csaba Karai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000-2008 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRVIEWFACTORY_H #define KRVIEWFACTORY_H // QtCore #include #include // QtGui #include // QtWidgets #include class KrView; class KConfig; /** Abstract container for KrView implementation classes. Created internally by KrViewFactory. */ class KrViewInstance { friend class KrView; public: inline int id() const { return m_id; } inline QString name() const { return m_name; } inline QString description() const { return m_description; } inline QString icon() const { return m_icon; } inline QKeySequence shortcut() const { return m_shortcut; } virtual KrView *create(QWidget *w, KConfig *cfg) = 0; protected: KrViewInstance(int id, const QString &name, const QString &desc, const QString &icon, const QKeySequence &shortcut); virtual ~KrViewInstance() {} private: const int m_id; const QString m_name; const QString m_description; const QString m_icon; const QKeySequence m_shortcut; QList m_objects; // direct access in KrView }; /** Factory for KrView implementations. This is a hidden singleton. */ class KrViewFactory { friend class KrViewInstance; public: static KrView *createView(int id, QWidget *widget, KConfig *cfg); static const QList ®isteredViews() { return self().m_registeredViews; } static int defaultViewId() { return self().m_defaultViewId; } private: KrViewFactory(); void init(); void registerView(KrViewInstance *); KrViewInstance *viewInstance(int id); static KrViewFactory &self(); QList m_registeredViews; int m_defaultViewId; }; #endif /* __KRVIEWFACTORY_H__ */ diff --git a/krusader/Panel/krcalcspacedialog.cpp b/krusader/Panel/krcalcspacedialog.cpp index c0dff8a7..658f5b89 100644 --- a/krusader/Panel/krcalcspacedialog.cpp +++ b/krusader/Panel/krcalcspacedialog.cpp @@ -1,140 +1,130 @@ -/*************************************************************************** - krcalcspacedialog.cpp - description - ------------------- - begin : Fri Jan 2 2004 - copyright : (C) 2004 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Shie Erlich * + * Copyright (C) 2004 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krcalcspacedialog.h" // QtCore #include // QtWidgets #include #include #include #include // QtGui #include #include #include "../krglobal.h" #include "../FileSystem/sizecalculator.h" KrCalcSpaceDialog::KrCalcSpaceDialog(QWidget *parent, SizeCalculator *calculator) : QDialog(parent), m_calculator(calculator) { setWindowTitle(i18n("Calculate Occupied Space")); QVBoxLayout *layout = new QVBoxLayout; setLayout(layout); layout->setSizeConstraint(QLayout::SetFixedSize); m_label = new QLabel(this); layout->addWidget(m_label); layout->addStretch(10); // buttons: Cancel is replaced with Ok when calculator is finished m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel); layout->addWidget(m_buttonBox); connect(m_buttonBox, &QDialogButtonBox::rejected, this, &KrCalcSpaceDialog::slotCancel); connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(m_calculator, &SizeCalculator::finished, this, &KrCalcSpaceDialog::slotCalculatorFinished); m_updateTimer = new QTimer(this); connect(m_updateTimer, &QTimer::timeout, this, &KrCalcSpaceDialog::updateResult); m_updateTimer->start(1000); updateResult(); } void KrCalcSpaceDialog::closeEvent(QCloseEvent *event) { if (event) { if (m_updateTimer->isActive()) slotCancel(); else accept(); } } void KrCalcSpaceDialog::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) { if (m_updateTimer->isActive()) slotCancel(); else reject(); } } void KrCalcSpaceDialog::showDialog(QWidget *parent, SizeCalculator *calculator) { KrCalcSpaceDialog *dialog = new KrCalcSpaceDialog(parent, calculator); dialog->show(); } void KrCalcSpaceDialog::slotCancel() { m_updateTimer->stop(); m_calculator->cancel(); reject(); // close and delete this dialog } void KrCalcSpaceDialog::slotCalculatorFinished() { m_buttonBox->clear(); QPushButton *okButton = m_buttonBox->addButton(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setFocus(); m_updateTimer->stop(); updateResult(); } void KrCalcSpaceDialog::updateResult() { const KIO::filesize_t totalSize = m_calculator->totalSize(); const unsigned long totalFiles = m_calculator->totalFiles(); const unsigned long totalDirs = m_calculator->totalDirs(); const QList urls = m_calculator->urls(); const QString fileName = urls.count() == 1 ? i18n("Name: %1\n", urls.first().fileName()) : QString(""); QString msg = fileName + i18n("Total occupied space: %1", KIO::convertSize(totalSize)); if (totalSize >= 1024) msg += i18np(" (%2 byte)", " (%2 bytes)", totalSize, QLocale().toString(totalSize)); msg += '\n'; msg += i18np("in %1 folder", "in %1 folders", totalDirs); msg += ' '; msg += i18np("and %1 file", "and %1 files", totalFiles); m_label->setText(msg); } diff --git a/krusader/Panel/krcalcspacedialog.h b/krusader/Panel/krcalcspacedialog.h index 33cef9f8..b91afba9 100644 --- a/krusader/Panel/krcalcspacedialog.h +++ b/krusader/Panel/krcalcspacedialog.h @@ -1,70 +1,60 @@ -/*************************************************************************** - krcalcspacedialog.h - description - ------------------- - begin : Fri Jan 2 2004 - copyright : (C) 2004 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2004 Shie Erlich * + * Copyright (C) 2004 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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 *); void keyPressEvent(QKeyEvent *e); 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/krerrordisplay.cpp b/krusader/Panel/krerrordisplay.cpp index 1656cb4a..774d827d 100644 --- a/krusader/Panel/krerrordisplay.cpp +++ b/krusader/Panel/krerrordisplay.cpp @@ -1,77 +1,67 @@ -/*************************************************************************** - krerrordisplay.cpp - ------------------- -copyright : (C) 2010 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krerrordisplay.h" #include #include "krcolorcache.h" KrErrorDisplay::KrErrorDisplay(QWidget *parent) : QLabel(parent), _currentDim(100) { setAutoFillBackground(true); _startColor = QColor(240,150,150); QPalette p(palette()); _targetColor = p.color(QPalette::Window); p.setColor(QPalette::Window, _startColor); setPalette(p); _dimTimer.setSingleShot(true); connect(&_dimTimer, SIGNAL(timeout()), this, SLOT(slotTimeout())); } void KrErrorDisplay::setText(QString text) { QLabel::setText(text); _currentDim = 100; QPalette p(palette()); p.setColor(QPalette::Window, _startColor); setPalette(p); _dimTimer.start(5000); } void KrErrorDisplay::slotTimeout() { _currentDim -= 2; dim(); if( _currentDim > 0) _dimTimer.start(50); } void KrErrorDisplay::dim() { QPalette p(palette()); p.setColor(QPalette::Window, KrColorCache::dimColor(_startColor, _currentDim, _targetColor)); setPalette(p); } diff --git a/krusader/Panel/krerrordisplay.h b/krusader/Panel/krerrordisplay.h index d5157ff4..c30ea6a5 100644 --- a/krusader/Panel/krerrordisplay.h +++ b/krusader/Panel/krerrordisplay.h @@ -1,62 +1,52 @@ -/*************************************************************************** - krerrordisplay.h - ------------------- -copyright : (C) 2010 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRERRORDISPLAY_H #define KRERRORDISPLAY_H // QtCore #include // QtGui #include // QtWidgets #include #include class KrErrorDisplay: public QLabel { Q_OBJECT public: explicit KrErrorDisplay(QWidget *parent); void setText(QString text); private slots: void slotTimeout(); private: void dim(); QTimer _dimTimer; QColor _startColor; QColor _targetColor; int _currentDim; }; #endif diff --git a/krusader/Panel/krlayoutfactory.cpp b/krusader/Panel/krlayoutfactory.cpp index 1d39e416..eb9699c0 100644 --- a/krusader/Panel/krlayoutfactory.cpp +++ b/krusader/Panel/krlayoutfactory.cpp @@ -1,325 +1,315 @@ -/*************************************************************************** - krlayoutfactory.cpp - ------------------- -copyright : (C) 2010 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krlayoutfactory.h" #include "listpanelframe.h" #include "../krglobal.h" // QtCore #include #include #include #include #include // QtWidgets #include #include #include #include // QtXml #include #include #include #define XMLFILE_VERSION "1.0" #define MAIN_FILE "layout.xml" #define MAIN_FILE_RC_PATH ":/" MAIN_FILE #define EXTRA_FILE_MASK "layouts/*.xml" #define DEFAULT_LAYOUT "krusader:default" bool KrLayoutFactory::_parsed = false; QDomDocument KrLayoutFactory::_mainDoc; QList KrLayoutFactory::_extraDocs; QString KrLayoutFactory::layoutDescription(QString layoutName) { if(layoutName == DEFAULT_LAYOUT) return i18nc("Default layout", "Default"); else if(layoutName == "krusader:compact") return i18n("Compact"); else if(layoutName == "krusader:classic") return i18n("Classic"); else return i18n("Custom layout: \"%1\"", layoutName); } bool KrLayoutFactory::parseFiles() { if (_parsed) return true; QString mainFilePath = QStandardPaths::locate(QStandardPaths::DataLocation, MAIN_FILE); if (!mainFilePath.isEmpty()) _parsed = parseFile(mainFilePath, _mainDoc); else qWarning() << "can't locate" << MAIN_FILE; if (!_parsed) _parsed = parseRessource(MAIN_FILE_RC_PATH, _mainDoc); if (!_parsed) return false; QStringList extraFilePaths = QStandardPaths::locateAll(QStandardPaths::DataLocation, EXTRA_FILE_MASK); foreach(const QString &path, extraFilePaths) { qWarning() << "extra file: " << path; QDomDocument doc; if (parseFile(path, doc)) _extraDocs << doc; } return true; } bool KrLayoutFactory::parseFile(QString path, QDomDocument &doc) { bool success = false; QFile file(path); if (file.open(QIODevice::ReadOnly)) return parseContent(file.readAll(), path, doc); else qWarning() << "can't open" << path; return success; } bool KrLayoutFactory::parseRessource(QString path, QDomDocument &doc) { QResource res(path); if (res.isValid()) { QByteArray data; if (res.isCompressed()) data = qUncompress(res.data(), res.size()); else data = QByteArray(reinterpret_cast(res.data()), res.size()); return parseContent(data, path, doc); } else { qWarning() << "resource does not exist:" << path; return false; } } bool KrLayoutFactory::parseContent(QByteArray content, QString fileName, QDomDocument &doc) { bool success = false; QString errorMsg; if (doc.setContent(content, &errorMsg)) { QDomElement root = doc.documentElement(); if (root.tagName() == "KrusaderLayout") { QString version = root.attribute("version"); if(version == XMLFILE_VERSION) success = true; else qWarning() << fileName << "has wrong version" << version << "- required is" << XMLFILE_VERSION; } else qWarning() << "root.tagName() != \"KrusaderLayout\""; } else qWarning() << "error parsing" << fileName << ":" << errorMsg; return success; } void KrLayoutFactory::getLayoutNames(QDomDocument doc, QStringList &names) { QDomElement root = doc.documentElement(); for(QDomElement e = root.firstChildElement(); ! e.isNull(); e = e.nextSiblingElement()) { if (e.tagName() == "layout") { QString name(e.attribute("name")); if (!name.isEmpty() && (name != DEFAULT_LAYOUT)) names << name; } } } QStringList KrLayoutFactory::layoutNames() { QStringList names; names << DEFAULT_LAYOUT; if (parseFiles()) { getLayoutNames(_mainDoc, names); foreach(const QDomDocument &doc, _extraDocs) getLayoutNames(doc, names); } return names; } QDomElement KrLayoutFactory::findLayout(QDomDocument doc, QString layoutName) { QDomElement root = doc.documentElement(); for(QDomElement e = root.firstChildElement(); ! e.isNull(); e = e.nextSiblingElement()) { if (e.tagName() == "layout" && e.attribute("name") == layoutName) return e; } return QDomElement(); } QLayout *KrLayoutFactory::createLayout(QString layoutName) { if(layoutName.isEmpty()) { KConfigGroup cg(krConfig, "PanelLayout"); layoutName = cg.readEntry("Layout", DEFAULT_LAYOUT); } QLayout *layout = 0; if (parseFiles()) { QDomElement layoutRoot; layoutRoot = findLayout(_mainDoc, layoutName); if (layoutRoot.isNull()) { foreach(const QDomDocument &doc, _extraDocs) { layoutRoot = findLayout(doc, layoutName); if(!layoutRoot.isNull()) break; } } if (layoutRoot.isNull()) { qWarning() << "no layout with name" << layoutName << "found"; if(layoutName != DEFAULT_LAYOUT) return createLayout(DEFAULT_LAYOUT); } else { layout = createLayout(layoutRoot, panel); } } if(layout) { foreach(const QString &name, widgets.keys()) { qWarning() << "widget" << name << "was not added to the layout"; widgets[name]->hide(); } } else qWarning() << "couldn't load layout" << layoutName; return layout; } QBoxLayout *KrLayoutFactory::createLayout(QDomElement e, QWidget *parent) { QBoxLayout *l = 0; bool horizontal = false; if(e.attribute("type") == "horizontal") { horizontal = true; l = new QHBoxLayout(); } else if(e.attribute("type") == "vertical") l = new QVBoxLayout(); else { qWarning() << "unknown layout type:" << e.attribute("type"); return 0; } l->setSpacing(0); l->setContentsMargins(0, 0, 0, 0); for(QDomElement child = e.firstChildElement(); ! child.isNull(); child = child.nextSiblingElement()) { if (child.tagName() == "layout") { if(QLayout *childLayout = createLayout(child, parent)) l->addLayout(childLayout); } else if(child.tagName() == "frame") { QWidget *frame = createFrame(child, parent); l->addWidget(frame); } else if(child.tagName() == "widget") { if(QWidget *w = widgets.take(child.attribute("name"))) l->addWidget(w); else qWarning() << "layout: no such widget:" << child.attribute("name"); } else if(child.tagName() == "hide_widget") { if(QWidget *w = widgets.take(child.attribute("name"))) w->hide(); else qWarning() << "layout: no such widget:" << child.attribute("name"); } else if(child.tagName() == "spacer") { if(horizontal) l->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed)); else l->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding)); } } return l; } QWidget *KrLayoutFactory::createFrame(QDomElement e, QWidget *parent) { KConfigGroup cg(krConfig, "PanelLayout"); QString color = cg.readEntry("FrameColor", "default"); if(color == "default") color = e.attribute("color"); else if(color == "none") color.clear(); int shadow = -1, shape = -1; QMetaEnum shadowEnum = QFrame::staticMetaObject.enumerator(QFrame::staticMetaObject.indexOfEnumerator("Shadow")); QString cfgShadow = cg.readEntry("FrameShadow", "default"); if(cfgShadow != "default") shadow = shadowEnum.keyToValue(cfgShadow.toLatin1().data()); if(shadow < 0) shadow = shadowEnum.keyToValue(e.attribute("shadow").toLatin1().data()); QMetaEnum shapeEnum = QFrame::staticMetaObject.enumerator(QFrame::staticMetaObject.indexOfEnumerator("Shape")); QString cfgShape = cg.readEntry("FrameShape", "default"); if(cfgShape!= "default") shape = shapeEnum.keyToValue(cfgShape.toLatin1().data()); if(shape < 0) shape = shapeEnum.keyToValue(e.attribute("shape").toLatin1().data()); QFrame *frame = new ListPanelFrame(parent, color); frame->setFrameStyle(shape | shadow); frame->setAcceptDrops(true); if(QLayout *l = createLayout(e, frame)) { l->setContentsMargins(frame->frameWidth(), frame->frameWidth(), frame->frameWidth(), frame->frameWidth()); frame->setLayout(l); } QObject::connect(frame, SIGNAL(dropped(QDropEvent*,QWidget*)), panel, SLOT(handleDrop(QDropEvent*))); if(!color.isEmpty()) QObject::connect(panel, SIGNAL(refreshColors(bool)), frame, SLOT(refreshColors(bool))); return frame; } diff --git a/krusader/Panel/krlayoutfactory.h b/krusader/Panel/krlayoutfactory.h index e8cac272..90e85b08 100644 --- a/krusader/Panel/krlayoutfactory.h +++ b/krusader/Panel/krlayoutfactory.h @@ -1,73 +1,63 @@ -/*************************************************************************** - krlayoutfactory.h - ------------------- -copyright : (C) 2010 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRLAYOUTFACTORY_H #define KRLAYOUTFACTORY_H // QtCore #include #include // QtXml #include class QWidget; class QLayout; class QBoxLayout; class KrLayoutFactory { public: KrLayoutFactory(QWidget *panel, QHash &widgets) : panel(panel), widgets(widgets) {} // creates the layout and adds the widgets to it QLayout *createLayout(QString layoutName = QString()); static QStringList layoutNames(); static QString layoutDescription(QString layoutName); private: QBoxLayout *createLayout(QDomElement e, QWidget *parent); QWidget *createFrame(QDomElement e, QWidget *parent); static bool parseFiles(); static bool parseFile(QString path, QDomDocument &doc); static bool parseRessource(QString path, QDomDocument &doc); static bool parseContent(QByteArray content, QString fileName, QDomDocument &doc); static void getLayoutNames(QDomDocument doc, QStringList &names); static QDomElement findLayout(QDomDocument doc, QString layoutName); QWidget *panel; QHash &widgets; static bool _parsed; static QDomDocument _mainDoc; static QList _extraDocs; }; #endif diff --git a/krusader/Panel/krpanel.cpp b/krusader/Panel/krpanel.cpp index a89425a1..1d39f8b5 100644 --- a/krusader/Panel/krpanel.cpp +++ b/krusader/Panel/krpanel.cpp @@ -1,50 +1,40 @@ -/*************************************************************************** - krpanel.cpp - ------------------- -copyright : (C) 2010 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krpanel.h" #include "panelfunc.h" #include "../abstractpanelmanager.h" QUrl KrPanel::virtualPath() const { return func->virtualDirectory(); } KrPanel *KrPanel::otherPanel() const { return _manager->otherManager()->currentPanel(); } bool KrPanel::isLeft() const { return _manager->isLeft(); } diff --git a/krusader/Panel/krpanel.h b/krusader/Panel/krpanel.h index a320bb56..3a0e33a7 100644 --- a/krusader/Panel/krpanel.h +++ b/krusader/Panel/krpanel.h @@ -1,65 +1,55 @@ -/*************************************************************************** - krpanel.h - ------------------- - copyright : (C) 2010 by Jan Lepper - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRPANEL_H #define KRPANEL_H // QtCore #include class AbstractPanelManager; class ListPanelFunc; class ListPanel; class KrView; class KrPanel { public: KrPanel(AbstractPanelManager *manager, ListPanel *panel, ListPanelFunc *func) : gui(panel), func(func), view(0), _manager(manager) {} virtual ~KrPanel() {} QUrl virtualPath() const; // the current directory path of this panel AbstractPanelManager *manager() const { return _manager; } KrPanel *otherPanel() const; bool isLeft() const; virtual void otherPanelChanged() = 0; ListPanel *const gui; ListPanelFunc *const func; KrView *view; protected: AbstractPanelManager *_manager; }; #endif diff --git a/krusader/Panel/krpreviewjob.cpp b/krusader/Panel/krpreviewjob.cpp index fe10c2ac..4bc2fb2b 100644 --- a/krusader/Panel/krpreviewjob.cpp +++ b/krusader/Panel/krpreviewjob.cpp @@ -1,172 +1,162 @@ -/*************************************************************************** - krpreviewjob.cpp - ------------------- -copyright : (C) 2009 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Jan Lepper * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krpreviewjob.h" #include "krpreviews.h" #include "PanelView/krview.h" #include "PanelView/krviewitem.h" #include "../FileSystem/fileitem.h" #include "../defaults.h" #include // QtWidgets #include #define ASSERT(what) if(!what) abort(); // how much items to process by a single job // view becomes unresponsive during load if set too high #define MAX_CHUNK_SIZE 50 KrPreviewJob::KrPreviewJob(KrPreviews *parent) : _job(0), _parent(parent) { _timer.setSingleShot(true); _timer.setInterval(0); connect(&_timer, SIGNAL(timeout()), SLOT(slotStartJob())); } KrPreviewJob::~KrPreviewJob() { doKill(); } void KrPreviewJob::scheduleItem(KrViewItem *item) { if(!_scheduled.contains(item)) { _scheduled.append(item); setTotalAmount(KJob::Files, totalAmount(KJob::Files) + 1); } if(!_job) _timer.start(); } void KrPreviewJob::removeItem(KrViewItem *item) { setTotalAmount(KJob::Files, totalAmount(KJob::Files) - _scheduled.removeAll(item)); if(_job) { doKill(); if(!_scheduled.isEmpty()) _timer.start(); } if(_scheduled.isEmpty()) emitResult(); } void KrPreviewJob::slotFailed(const KFileItem & item) { slotGotPreview(item, QPixmap()); } void KrPreviewJob::slotGotPreview(const KFileItem & item, const QPixmap & preview) { KrViewItem *vi = _hash[item]; ASSERT(vi); _scheduled.removeOne(vi); const FileItem *file = vi->getFileItem(); _parent->addPreview(file, preview); vi->redraw(); setProcessedAmount(KJob::Files, processedAmount(KJob::Files) + 1); emitPercent(processedAmount(KJob::Files), totalAmount(KJob::Files)); } void KrPreviewJob::slotStartJob() { ASSERT(_job == 0); ASSERT(!_scheduled.isEmpty()); _hash.clear(); sort(); int size = _parent->_view->fileIconSize(); KFileItemList list; for(int i = 0; i < _scheduled.count() && i < MAX_CHUNK_SIZE; i++) { KFileItem fi(_scheduled[i]->getFileItem()->getUrl(), 0, 0); list.append(fi); _hash.insert(fi, _scheduled[i]); } QStringList allPlugins = KIO::PreviewJob::availablePlugins(); _job = new KIO::PreviewJob(list, QSize(size, size), &allPlugins); _job->setOverlayIconAlpha(0); _job->setOverlayIconSize(0); _job->setScaleType(KIO::PreviewJob::ScaledAndCached); connect(_job, SIGNAL(gotPreview(KFileItem,QPixmap)), SLOT(slotGotPreview(KFileItem,QPixmap))); connect(_job, SIGNAL(failed(KFileItem)), SLOT(slotFailed(KFileItem))); connect(_job, SIGNAL(result(KJob*)), SLOT(slotJobResult(KJob*))); } void KrPreviewJob::slotJobResult(KJob *job) { (void) job; if(!disconnect(_job, 0, this, 0)) abort(); _job = 0; _hash.clear(); if(_scheduled.isEmpty()) emitResult(); else _timer.start(); } // move currently visible items to beginning of the list void KrPreviewJob::sort() { for(int i = 0, visible_end = 0; i < _scheduled.count(); i++) { KrViewItem *item = _scheduled[i]; if(_parent->_view->widget()->rect().intersects(item->itemRect())) { if(i != visible_end) _scheduled.move(i, visible_end); visible_end++; } } } bool KrPreviewJob::doKill() { _timer.stop(); if(_job) { if(!disconnect(_job, 0, this, 0)) abort(); if(!_job->kill()) abort(); _job = 0; } _hash.clear(); return true; } diff --git a/krusader/Panel/krpreviewjob.h b/krusader/Panel/krpreviewjob.h index 99a15b96..5b1299c6 100644 --- a/krusader/Panel/krpreviewjob.h +++ b/krusader/Panel/krpreviewjob.h @@ -1,76 +1,66 @@ -/*************************************************************************** - krpreviewjob.h - ------------------- -copyright : (C) 2009 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Jan Lepper * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef 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: virtual void start() Q_DECL_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(); void scheduleItem(KrViewItem *item); void removeItem(KrViewItem *item); void sort(); virtual bool doKill() Q_DECL_OVERRIDE; }; #endif // __krpreviewjob__ diff --git a/krusader/Panel/krpreviews.cpp b/krusader/Panel/krpreviews.cpp index 3894a2dd..95c91ae2 100644 --- a/krusader/Panel/krpreviews.cpp +++ b/krusader/Panel/krpreviews.cpp @@ -1,140 +1,130 @@ -/*************************************************************************** - krpreviews.cpp - ------------------- -copyright : (C) 2009 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Jan Lepper * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krpreviews.h" #include "krpreviewjob.h" #include "krcolorcache.h" #include "PanelView/krview.h" #include "PanelView/krviewitem.h" #include "../FileSystem/fileitem.h" #include "../defaults.h" #include #define ASSERT(what) if(!what) abort(); KrPreviews::KrPreviews(KrView *view) : _job(0), _view(view) { _dim = KrColorCache::getColorCache().getDimSettings(_dimColor, _dimFactor); connect(&KrColorCache::getColorCache(), SIGNAL(colorsRefreshed()), SLOT(slotRefreshColors())); } KrPreviews::~KrPreviews() { clear(); } void KrPreviews::clear() { if(_job) { _job->kill(KJob::EmitResult); _job = 0; } _previews.clear(); _previewsInactive.clear(); } void KrPreviews::update() { if(_job) return; for (KrViewItem *it = _view->getFirst(); it != 0; it = _view->getNext(it)) { if(!_previews.contains(it->getFileItem())) updatePreview(it); } } void KrPreviews::deletePreview(KrViewItem *item) { if(_job) { _job->removeItem(item); } removePreview(item->getFileItem()); } void KrPreviews::updatePreview(KrViewItem *item) { if(!_job) { _job = new KrPreviewJob(this); connect(_job, SIGNAL(result(KJob*)), SLOT(slotJobResult(KJob*))); _view->op()->emitPreviewJobStarted(_job); } _job->scheduleItem(item); } bool KrPreviews::getPreview(const FileItem *file, QPixmap &pixmap, bool active) { if(active || !_dim) pixmap = _previews.value(file); else pixmap = _previewsInactive.value(file); return !pixmap.isNull(); } void KrPreviews::slotJobResult(KJob *job) { (void) job; _job = 0; } void KrPreviews::slotRefreshColors() { clear(); _dim = KrColorCache::getColorCache().getDimSettings(_dimColor, _dimFactor); update(); } void KrPreviews::addPreview(const FileItem *file, const QPixmap &preview) { QPixmap active, inactive; if(preview.isNull()) { active = KrView::getIcon((FileItem *)file, true, _view->fileIconSize()); if(_dim) inactive = KrView::getIcon((FileItem *)file, false, _view->fileIconSize()); } else { active = KrView::processIcon(preview, false, _dimColor, _dimFactor, file->isSymLink()); if(_dim) inactive = KrView::processIcon(preview, true, _dimColor, _dimFactor, file->isSymLink()); } _previews.insert(file, active); if(_dim) _previewsInactive.insert(file, inactive); } void KrPreviews::removePreview(const FileItem *file) { _previews.remove(file); _previewsInactive.remove(file); } diff --git a/krusader/Panel/krpreviews.h b/krusader/Panel/krpreviews.h index bff2705b..63cb0455 100644 --- a/krusader/Panel/krpreviews.h +++ b/krusader/Panel/krpreviews.h @@ -1,79 +1,69 @@ -/*************************************************************************** - krpreviews.h - ------------------- -copyright : (C) 2009 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2009 Jan Lepper * + * Copyright (C) 2009-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRPREVIEWS_H #define KRPREVIEWS_H // QtCore #include #include // QtGui #include #include class KJob; class KrView; class KrViewItem; class KrPreviewJob; class FileItem; class KrPreviews: public QObject { friend class KrPreviewJob; Q_OBJECT public: explicit KrPreviews(KrView *view); ~KrPreviews(); bool getPreview(const FileItem* file, QPixmap &pixmap, bool active); void updatePreview(KrViewItem *item); void deletePreview(KrViewItem *item); //updates all items for which no preview has been loaded yet void update(); void clear(); protected slots: void slotRefreshColors(); void slotJobResult(KJob *job); protected: void addPreview(const FileItem *file, const QPixmap &preview); void removePreview(const FileItem* file); KrPreviewJob *_job; bool _dim; QColor _dimColor; int _dimFactor; QHash _previews; QHash _previewsInactive; KrView *_view; }; #endif // __krpreviews__ diff --git a/krusader/Panel/listpanel.cpp b/krusader/Panel/listpanel.cpp index 726f8f0e..4b2fefda 100644 --- a/krusader/Panel/listpanel.cpp +++ b/krusader/Panel/listpanel.cpp @@ -1,1388 +1,1379 @@ -/*************************************************************************** - listpanel.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "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 "../kicons.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, 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: virtual void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE { panel->slotFocusOnMe(); action->trigger(); } ListPanel *panel; QAction *action; }; ///////////////////////////////////////////////////// // The list panel constructor // ///////////////////////////////////////////////////// ListPanel::ListPanel(QWidget *parent, AbstractPanelManager *manager, KConfigGroup cfg) : QWidget(parent), KrPanel(manager, this, new ListPanelFunc(this)), panelType(-1), colorMask(255), compareMode(false), previewJob(0), inlineRefreshJob(0), searchBar(0), cdRootButton(0), cdUpButton(0), sidebarButton(0), sidebar(0), fileSystemError(0), _navigatorUrl(), _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, SIGNAL(aboutToShow()), this, SLOT(slotFocusOnMe())); connect(mediaButton, SIGNAL(openUrl(QUrl)), func, SLOT(openUrl(QUrl))); connect(mediaButton, SIGNAL(newTab(QUrl)), SLOT(newTab(QUrl))); 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, SIGNAL(aboutToShow()), this, SLOT(slotFocusOnMe())); connect(historyButton, SIGNAL(gotoPos(int)), func, SLOT(historyGotoPos(int))); ADD_WIDGET(historyButton); // bookmarks button bookmarksButton = new KrBookmarkButton(this); connect(bookmarksButton, SIGNAL(aboutToShow()), this, SLOT(slotFocusOnMe())); connect(bookmarksButton, SIGNAL(openUrl(QUrl)), func, SLOT(openUrl(QUrl))); 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, SIGNAL(returnPressed()), this, SLOT(slotFocusOnMe())); connect(urlNavigator, &KUrlNavigator::urlChanged, this, &ListPanel::slotNavigatorUrlChanged); connect(urlNavigator->editor()->lineEdit(), &QLineEdit::editingFinished, this, &ListPanel::resetNavigatorMode); connect(urlNavigator, SIGNAL(tabRequested(QUrl)), this, SLOT(newTab(QUrl))); connect(urlNavigator, SIGNAL(urlsDropped(QUrl,QDropEvent*)), this, SLOT(handleDrop(QUrl,QDropEvent*))); ADD_WIDGET(urlNavigator); // toolbar QWidget * toolbar = new QWidget(this); QHBoxLayout * 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); QVBoxLayout *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(krLoader->loadIcon("dialog-cancel", KIconLoader::Toolbar, 16)); 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(krLoader->loadIcon("dialog-cancel", KIconLoader::Toolbar, 16)); connect(cancelProgressButton, SIGNAL(clicked()), this, SLOT(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(krLoader->loadIcon("exchange-positions", KIconLoader::Toolbar, 16)); 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(krLoader->loadIcon("arrow-up", KIconLoader::Toolbar, 16)); 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(QIcon::fromTheme("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( QIcon::fromTheme(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 QVBoxLayout *v = new QVBoxLayout; v->setContentsMargins(0, 0, 0, 0); v->setSpacing(0); QHBoxLayout *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(), SIGNAL(colorsRefreshed()), this, SLOT(refreshColors())); connect(krApp, SIGNAL(shutdown()), SLOT(cancelProgress())); } ListPanel::~ListPanel() { cancelProgress(); delete view; view = 0; 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(), SIGNAL(goHome()), func, SLOT(home())); connect(view->op(), SIGNAL(dirUp()), func, SLOT(dirUp())); connect(view->op(), &KrViewOperator::defaultDeleteFiles, func, &ListPanelFunc::defaultDeleteFiles); connect(view->op(), SIGNAL(middleButtonClicked(KrViewItem*)), SLOT(newTab(KrViewItem*))); connect(view->op(), SIGNAL(currentChanged(KrViewItem*)), SLOT(slotCurrentChanged(KrViewItem*))); connect(view->op(), SIGNAL(renameItem(QString,QString)), func, SLOT(rename(QString,QString))); connect(view->op(), SIGNAL(executed(QString)), func, SLOT(execute(QString))); connect(view->op(), SIGNAL(goInside(QString)), func, SLOT(goInside(QString))); connect(view->op(), SIGNAL(needFocus()), this, SLOT(slotFocusOnMe())); connect(view->op(), SIGNAL(selectionChanged()), this, SLOT(slotUpdateTotals())); connect(view->op(), SIGNAL(itemDescription(QString)), krApp, SLOT(statusBarUpdate(QString))); connect(view->op(), SIGNAL(contextMenu(QPoint)), this, SLOT(popRightClickMenu(QPoint))); connect(view->op(), SIGNAL(emptyContextMenu(QPoint)), this, SLOT(popEmptyRightClickMenu(QPoint))); connect(view->op(), SIGNAL(letsDrag(QStringList,QPixmap)), this, SLOT(startDragging(QStringList,QPixmap))); connect(view->op(), &KrViewOperator::gotDrop, this, [this](QDropEvent *event) {handleDrop(event, true); }); connect(view->op(), SIGNAL(previewJobStarted(KJob*)), this, SLOT(slotPreviewJobStarted(KJob*))); connect(view->op(), SIGNAL(refreshActions()), krApp->viewActions(), SLOT(refreshActions())); connect(view->op(), SIGNAL(currentChanged(KrViewItem*)), func->history, SLOT(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) { QKeyEvent *ke = static_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) { QKeyEvent *ke = static_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) { QKeyEvent *ke = static_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(krLoader->loadIcon("arrow-down", KIconLoader::Toolbar, 16)); sidebarButton->setToolTip(i18n("Close the Sidebar")); sidebarPositionButton->show(); } else { sidebarSplitterSizes.clear(); sidebarSplitterSizes = sidebarSplitter->sizes(); sidebar->hide(); sidebarButton->setIcon(krLoader->loadIcon("arrow-up", KIconLoader::Toolbar, 16)); 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 != 0; item = view->getNext(item)) { if (item->name() == "..") continue; for (otherItem = otherPanel()->view->getFirst(); otherItem != 0 && otherItem->name() != item->name(); otherItem = otherPanel()->view->getNext(otherItem)); bool isSingle = (otherItem == 0), 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)->getTime_t() > otherPanel()->func->getFileItem(otherItem)->getTime_t(); } 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::refreshColors() { view->refreshColors(); emit refreshColors(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); refreshColors(); 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(0); 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()) : 0; 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(QStringList names, QPixmap px) { if (names.isEmpty()) { // avoid dragging empty urls return; } QList urls = func->files()->getUrls(names); QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; drag->setPixmap(px); mimeData->setUrls(urls); drag->setMimeData(mimeData); drag->start(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() { QString name = view->getCurrentItem(); if (name != "..") return name; else return QString(); } 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 = 0; 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, SIGNAL(infoMessage(KJob*,QString)), SLOT(inlineRefreshInfoMessage(KJob*,QString))); connect(job, SIGNAL(percent(KJob*,ulong)), SLOT(inlineRefreshPercent(KJob*,ulong))); connect(job, SIGNAL(result(KJob*)), this, SLOT(inlineRefreshListResult(KJob*))); inlineRefreshJob = job; totals->setText(i18n(">> Reading...")); cancelProgressButton->show(); } void ListPanel::cancelProgress() { if (inlineRefreshJob) { disconnect(inlineRefreshJob, 0, this, 0); inlineRefreshJob->kill(KJob::EmitResult); inlineRefreshListResult(0); } if(previewJob) { disconnect(previewJob, 0, this, 0); previewJob->kill(KJob::EmitResult); slotPreviewJobResult(0); } } 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, 0, this, 0); inlineRefreshJob = 0; // 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 = url; } void ListPanel::slotFilesystemError(QString msg) { refreshColors(); 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(); } void ListPanel::showSearchFilter() { 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 : 0); } 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 f1be8d22..f4237770 100644 --- a/krusader/Panel/listpanel.h +++ b/krusader/Panel/listpanel.h @@ -1,267 +1,257 @@ -/*************************************************************************** - listpanel.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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, KConfigGroup cfg = KConfigGroup()); ~ListPanel(); virtual void otherPanelChanged() Q_DECL_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(); 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 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 refreshColors(); 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 showSearchFilter(); void jumpBack(); void setJumpBack() { setJumpBack(virtualPath()); } ///////////////////////// service functions - called internally //////////////////////// void prepareToDelete(); // internal use only protected: virtual void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; virtual void mousePressEvent(QMouseEvent*) Q_DECL_OVERRIDE { slotFocusOnMe(); } virtual void showEvent(QShowEvent *) Q_DECL_OVERRIDE; virtual void hideEvent(QHideEvent *) Q_DECL_OVERRIDE; virtual bool eventFilter(QObject * watched, QEvent * e) Q_DECL_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 handleDrop(QDropEvent *event, bool onView = false); // handle drops on frame or view void handleDrop(const QUrl &destination, QDropEvent *event); // handle drops with destination void startDragging(QStringList, 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(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); // emmited 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 refreshColors(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/listpanelactions.cpp b/krusader/Panel/listpanelactions.cpp index fce7e3f0..005db4bb 100644 --- a/krusader/Panel/listpanelactions.cpp +++ b/krusader/Panel/listpanelactions.cpp @@ -1,226 +1,215 @@ -/*************************************************************************** - listpanelactions.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -copyright : (C) 2010 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "listpanelactions.h" #include "listpanel.h" #include "panelfunc.h" #include "PanelView/krviewfactory.h" #include "../krmainwindow.h" #include "../Dialogs/krdialogs.h" #include "../KViewer/krviewer.h" // QtCore #include // QtWidgets #include #include #include ListPanelActions::ListPanelActions(QObject *parent, KrMainWindow *mainWindow) : ActionsBase(parent, mainWindow) { // set view type QSignalMapper *mapper = new QSignalMapper(this); connect(mapper, SIGNAL(mapped(int)), SLOT(setView(int))); QActionGroup *group = new QActionGroup(this); group->setExclusive(true); QList views = KrViewFactory::registeredViews(); for(int i = 0; i < views.count(); i++) { KrViewInstance *inst = views[i]; QAction *action = new QAction(QIcon::fromTheme(inst->icon()), inst->description(), group); action->setCheckable(true); connect(action, SIGNAL(triggered()), mapper, SLOT(map())); mapper->setMapping(action, inst->id()); _mainWindow->actions()->addAction("view" + QString::number(i), action); _mainWindow->actions()->setDefaultShortcut(action, inst->shortcut()); setViewActions.insert(inst->id(), action); } // standard actions actHistoryBackward = stdAction(KStandardAction::Back, _func, SLOT(historyBackward())); actHistoryForward = stdAction(KStandardAction::Forward, _func, SLOT(historyForward())); //FIXME: second shortcut for up: see actDirUp // KStandardAction::up( this, SLOT(dirUp()), actionCollection )->setShortcut(Qt::Key_Backspace); /* Shortcut disabled because of the Terminal Emulator bug. */ actDirUp = stdAction(KStandardAction::Up, _func, SLOT(dirUp())); actHome = stdAction(KStandardAction::Home, _func, SLOT(home())); actCut = stdAction(KStandardAction::Cut, _func, SLOT(cut())); actCut->setText(i18n("Cut to Clipboard")); // removing alternative shift+del shortcut, it is used for the alternative delete files action QList cutShortcuts = actCut->shortcuts(); cutShortcuts.removeAll(QKeySequence(Qt::SHIFT | Qt::Key_Delete)); _mainWindow->actions()->setDefaultShortcuts(actCut, cutShortcuts); actCopy = stdAction(KStandardAction::Copy, _func, SLOT(copyToClipboard())); actCopy->setText(i18n("Copy to Clipboard")); actPaste = stdAction(KStandardAction::Paste, _func, SLOT(pasteFromClipboard())); actPaste->setText(i18n("Paste from Clipboard")); // Fn keys actRenameF2 = action(i18n("Rename"), "edit-rename", Qt::Key_F2, _func, SLOT(rename()) , "F2_Rename"); actViewFileF3 = action(i18n("View File"), 0, Qt::Key_F3, _func, SLOT(view()), "F3_View"); actEditFileF4 = action(i18n("Edit File"), 0, Qt::Key_F4, _func, SLOT(edit()) , "F4_Edit"); actCopyF5 = action(i18n("Copy to other panel"), 0, Qt::Key_F5, _func, SLOT(copyFiles()) , "F5_Copy"); actMoveF6 = action(i18n("Move to other panel"), 0, Qt::Key_F6, _func, SLOT(moveFiles()) , "F6_Move"); actCopyDelayedF5 = action(i18n("Copy delayed..."), 0, Qt::SHIFT + Qt::Key_F5, _func, SLOT(copyFilesDelayed()) , "F5_Copy_Queue"); actMoveDelayedShiftF6 = action(i18n("Move delayed..."), 0, Qt::SHIFT + Qt::Key_F6, _func, SLOT(moveFilesDelayed()) , "F6_Move_Queue"); actNewFolderF7 = action(i18n("New Folder..."), "folder-new", Qt::Key_F7, _func, SLOT(mkdir()) , "F7_Mkdir"); actDeleteF8 = action(i18n("Delete"), "edit-delete", Qt::Key_F8, _func, SLOT(defaultDeleteFiles()) , "F8_Delete"); actTerminalF9 = action(i18n("Start Terminal Here"), "utilities-terminal", Qt::Key_F9, _func, SLOT(terminal()) , "F9_Terminal"); action(i18n("&New Text File..."), "document-new", Qt::SHIFT + Qt::Key_F4, _func, SLOT(editNew()), "edit_new_file"); action(i18n("F3 View Dialog"), 0, Qt::SHIFT + Qt::Key_F3, _func, SLOT(viewDlg()), "F3_ViewDlg"); // file operations action(i18n("Right-click Menu"), 0, Qt::Key_Menu, _gui, SLOT(rightclickMenu()), "rightclick menu"); actProperties = action(i18n("&Properties..."), "document-properties", Qt::ALT + Qt::Key_Return, _func, SLOT(properties()), "properties"); actCompDirs = action(i18n("&Compare Folders"), "kr_comparedirs", Qt::ALT + Qt::SHIFT + Qt::Key_C, _gui, SLOT(compareDirs()), "compare dirs"); actCalculate = action(i18n("Calculate &Occupied Space"), "accessories-calculator", 0, _func, SLOT(calcSpace()), "calculate"); actPack = action(i18n("Pac&k..."), "archive-insert", Qt::ALT + Qt::SHIFT + Qt::Key_P, _func, SLOT(pack()), "pack"); actUnpack = action(i18n("&Unpack..."), "archive-extract", Qt::ALT + Qt::SHIFT + Qt::Key_U, _func, SLOT(unpack()), "unpack"); actCreateChecksum = action(i18n("Create Checksum..."), "document-edit-sign", 0, _func, SLOT(createChecksum()), "create checksum"); actMatchChecksum = action(i18n("Verify Checksum..."), "document-edit-decrypt-verify", 0, _func, SLOT(matchChecksum()), "match checksum"); action(i18n("New Symlink..."), 0, Qt::CTRL + Qt::ALT + Qt::Key_S, _func, SLOT(krlink()), "new symlink"); actTest = action(i18n("T&est Archive"), "archive-extract", Qt::ALT + Qt::SHIFT + Qt::Key_E, _func, SLOT(testArchive()), "test archives"); action(i18n("Alternative Delete"), "edit-delete", Qt::Key_Delete + Qt::CTRL, _func, SLOT(alternativeDeleteFiles()), "alternative delete"); // navigation actRoot = action(i18n("Root"), "folder-red", Qt::CTRL + Qt::Key_Backspace, _func, SLOT(root()), "root"); actCdToOther = action(i18n("Go to Other Panel's Folder"), 0, Qt::CTRL + Qt::Key_Equal, _func, SLOT(cdToOtherPanel()), "cd to other panel"); action(i18n("&Reload"), "view-refresh", Qt::CTRL + Qt::Key_R, _func, SLOT(refresh()), "std_redisplay"); actCancelRefresh = action(i18n("Cancel Refresh of View"), "dialog-cancel", 0, _gui, SLOT(cancelProgress()), "cancel refresh"); actFTPNewConnect = action(i18n("New Net &Connection..."), "network-connect", Qt::CTRL + Qt::Key_N, _func, SLOT(newFTPconnection()), "ftp new connection"); actFTPDisconnect = action(i18n("Disconnect &from Net"), "network-disconnect", Qt::SHIFT + Qt::CTRL + Qt::Key_D, _func, SLOT(FTPDisconnect()), "ftp disconnect"); action(i18n("Sync Panels"), 0, Qt::ALT + Qt::SHIFT + Qt::Key_O, _func, SLOT(syncOtherPanel()), "sync panels"); actJumpBack = action(i18n("Jump Back"), "go-jump", Qt::CTRL + Qt::Key_J, _gui, SLOT(jumpBack()), "jump_back"); actSetJumpBack = action(i18n("Set Jump Back Point"), "go-jump-definition", Qt::CTRL + Qt::SHIFT + Qt::Key_J, _gui, SLOT(setJumpBack()), "set_jump_back"); actSyncBrowse = action(i18n("S&ynchron Folder Changes"), "kr_syncbrowse_off", Qt::ALT + Qt::SHIFT + Qt::Key_Y, _gui, SLOT(toggleSyncBrowse()), "sync browse"); actLocationBar = action(i18n("Go to Location Bar"), 0, Qt::CTRL + Qt::Key_L, _gui, SLOT(editLocation()), "location_bar"); actSearchBar = action(i18n("Find in folder..."), 0, Qt::CTRL + Qt::Key_F, _gui, SLOT(showSearchBar()), "search bar"); action(i18n("Open search filter"), 0, Qt::CTRL + Qt::Key_I, _gui, SLOT(showSearchFilter()), "search bar filter"); toggleAction(i18n("Toggle Sidebar"), 0, Qt::ALT + Qt::Key_Down, _gui, SLOT(toggleSidebar()), "toggle sidebar"); action(i18n("Bookmarks"), 0, Qt::CTRL + Qt::Key_D, _gui, SLOT(openBookmarks()), "bookmarks"); action(i18n("Left Bookmarks"), 0, 0, this, SLOT(openLeftBookmarks()), "left bookmarks"); action(i18n("Right Bookmarks"), 0, 0, this, SLOT(openRightBookmarks()), "right bookmarks"); action(i18n("History"), 0, Qt::CTRL + Qt::Key_H, _gui, SLOT(openHistory()), "history"); action(i18n("Left History"), 0, Qt::ALT + Qt::CTRL + Qt::Key_Left, this, SLOT(openLeftHistory()), "left history"); action(i18n("Right History"), 0, Qt::ALT + Qt::CTRL + Qt::Key_Right, this, SLOT(openRightHistory()), "right history"); action(i18n("Media"), 0, Qt::CTRL + Qt::Key_M, _gui, SLOT(openMedia()), "media"); action(i18n("Left Media"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Left, this, SLOT(openLeftMedia()), "left media"); action(i18n("Right Media"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Right, this, SLOT(openRightMedia()), "right media"); // and at last we can set the tool-tips actRoot->setToolTip(i18n("ROOT (/)")); actRenameF2->setToolTip(i18n("Rename file, folder, etc.")); actViewFileF3->setToolTip(i18n("Open file in viewer.")); actEditFileF4->setToolTip(i18n("

Edit file.

" "

The editor can be defined in Konfigurator, " "default is internal editor.

")); actCopyF5->setToolTip(i18n("Copy file from one panel to the other.")); actMoveF6->setToolTip(i18n("Move file from one panel to the other.")); actNewFolderF7->setToolTip(i18n("Create folder in current panel.")); actDeleteF8->setToolTip(i18n("Delete file, folder, etc.")); actTerminalF9->setToolTip(i18n("

Open terminal in current folder.

" "

The terminal can be defined in Konfigurator, " "default is konsole.

")); } void ListPanelActions::activePanelChanged() { _gui.reconnect(activePanel()->gui); _func.reconnect(activePanel()->func); } void ListPanelActions::guiUpdated() { QList actions; foreach(QAction *action, setViewActions.values()) actions << action; static_cast(_mainWindow)->plugActionList("view_actionlist", actions); } inline KrPanel *ListPanelActions::activePanel() { return static_cast(_mainWindow)->activePanel(); } inline KrPanel *ListPanelActions::leftPanel() { return static_cast(_mainWindow)->leftPanel(); } inline KrPanel *ListPanelActions::rightPanel() { return static_cast(_mainWindow)->rightPanel(); } // set view type void ListPanelActions::setView(int id) { activePanel()->gui->changeType(id); } // navigation void ListPanelActions::openLeftBookmarks() { leftPanel()->gui->openBookmarks(); } void ListPanelActions::openRightBookmarks() { rightPanel()->gui->openBookmarks(); } void ListPanelActions::openLeftHistory() { leftPanel()->gui->openHistory(); } void ListPanelActions::openRightHistory() { rightPanel()->gui->openHistory(); } void ListPanelActions::openLeftMedia() { leftPanel()->gui->openMedia(); } void ListPanelActions::openRightMedia() { rightPanel()->gui->openMedia(); } diff --git a/krusader/Panel/listpanelactions.h b/krusader/Panel/listpanelactions.h index 062c5dcb..4e799e41 100644 --- a/krusader/Panel/listpanelactions.h +++ b/krusader/Panel/listpanelactions.h @@ -1,88 +1,76 @@ -/*************************************************************************** - listpanelactions.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - copyright : (C) 2010 by Jan Lepper - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef LISTPANELACTIONS_H #define LISTPANELACTIONS_H #include "../actionsbase.h" // QtWidgets #include class KrMainWindow; class KrPanel; class ListPanelFunc; class ListPanelActions : public ActionsBase { Q_OBJECT public: ListPanelActions(QObject *parent, KrMainWindow *mainWindow); public slots: // set view type void setView(int id); // navigation void openLeftBookmarks(); void openRightBookmarks(); void openLeftHistory(); void openRightHistory(); void openLeftMedia(); void openRightMedia(); void activePanelChanged(); void guiUpdated(); public: QAction *actRenameF2, *actViewFileF3, *actEditFileF4, *actCopyF5, *actMoveF6, *actNewFolderF7, *actDeleteF8, *actTerminalF9; QAction *actCopyDelayedF5, *actMoveDelayedShiftF6; QAction *actProperties, *actPack, *actUnpack, *actTest, *actCompDirs, *actCalculate, *actSync; QAction *actFTPConnect, *actFTPNewConnect, *actFTPDisconnect; QAction *actLocationBar, *actSearchBar, *actJumpBack, *actSetJumpBack; QAction *actCreateChecksum, *actMatchChecksum; QAction *actCopy, *actCut, *actPaste; QAction *actHistoryBackward, *actHistoryForward, *actDirUp, *actRoot, *actHome, *actCdToOther; QAction *actSyncBrowse, *actCancelRefresh; QHash setViewActions; protected: KrPanel *activePanel(); KrPanel *leftPanel(); KrPanel *rightPanel(); ActionGroup _gui, _func; }; #endif // LISTPANELACTIONS_H diff --git a/krusader/Panel/panelfunc.cpp b/krusader/Panel/panelfunc.cpp index 08749080..ec02e2d1 100644 --- a/krusader/Panel/panelfunc.cpp +++ b/krusader/Panel/panelfunc.cpp @@ -1,1299 +1,1290 @@ -/*************************************************************************** - panelfunc.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "panelfunc.h" // QtCore #include #include #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dirhistoryqueue.h" #include "krcalcspacedialog.h" #include "krerrordisplay.h" #include "listpanel.h" #include "listpanelactions.h" #include "PanelView/krview.h" #include "PanelView/krviewitem.h" #include "../krglobal.h" #include "../krslots.h" #include "../kractions.h" #include "../defaults.h" #include "../abstractpanelmanager.h" #include "../krservices.h" #include "../Archive/krarchandler.h" #include "../Archive/packjob.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/virtualfilesystem.h" #include "../FileSystem/krpermhandler.h" #include "../FileSystem/filesystemprovider.h" #include "../FileSystem/sizecalculator.h" #include "../Dialogs/packgui.h" #include "../Dialogs/krdialogs.h" #include "../Dialogs/krpleasewait.h" #include "../Dialogs/krspwidgets.h" #include "../Dialogs/checksumdlg.h" #include "../KViewer/krviewer.h" #include "../MountMan/kmountman.h" QPointer ListPanelFunc::copyToClipboardOrigin; ListPanelFunc::ListPanelFunc(ListPanel *parent) : QObject(parent), panel(parent), fileSystemP(0), urlManuallyEntered(false), _isPaused(true), _refreshAfterPaused(true), _quickSizeCalculator(0) { history = new DirHistoryQueue(panel); delayTimer.setSingleShot(true); connect(&delayTimer, SIGNAL(timeout()), this, SLOT(doRefresh())); } ListPanelFunc::~ListPanelFunc() { if (fileSystemP) { fileSystemP->deleteLater(); } delete history; if (_quickSizeCalculator) _quickSizeCalculator->deleteLater(); } bool ListPanelFunc::isSyncing(const QUrl &url) { if(otherFunc()->otherFunc() == this && panel->otherPanel()->gui->syncBrowseButton->isChecked() && !otherFunc()->syncURL.isEmpty() && otherFunc()->syncURL == url) return true; return false; } void ListPanelFunc::openFileNameInternal(const QString &name, bool externallyExecutable) { if (name == "..") { dirUp(); return; } FileItem *fileitem = files()->getFileItem(name); if (fileitem == 0) return; QUrl url = files()->getUrl(name); if (fileitem->isDir()) { panel->view->setNameToMakeCurrent(QString()); openUrl(url); return; } QString mime = fileitem->getMime(); QUrl arcPath = browsableArchivePath(name); if (!arcPath.isEmpty()) { bool browseAsDirectory = !externallyExecutable || (KConfigGroup(krConfig, "Archives").readEntry("ArchivesAsDirectories", _ArchivesAsDirectories) && (KRarcHandler::arcSupported(mime) || KrServices::isoSupported(mime))); if (browseAsDirectory) { openUrl(arcPath); return; } } if (externallyExecutable) { if (KRun::isExecutableFile(url, mime)) { runCommand(KShell::quoteArg(url.path())); return; } KService::Ptr service = KMimeTypeTrader::self()->preferredService(mime); if(service) { runService(*service, QList() << url); return; } displayOpenWithDialog(QList() << url); } } QUrl ListPanelFunc::cleanPath(const QUrl &urlIn) { QUrl url = urlIn; url.setPath(QDir::cleanPath(url.path())); if (!url.isValid() || url.isRelative()) { if (url.url() == "~") url = QUrl::fromLocalFile(QDir::homePath()); else if (!url.url().startsWith('/')) { // possible relative URL - translate to full URL url = files()->currentDirectory(); url.setPath(url.path() + '/' + urlIn.path()); } } url.setPath(QDir::cleanPath(url.path())); return url; } void ListPanelFunc::openUrl(const QUrl &url, const QString& nameToMakeCurrent, bool manuallyEntered) { qDebug() << "URL=" << url.toDisplayString() << "; name to current=" << nameToMakeCurrent; if (panel->syncBrowseButton->isChecked()) { //do sync-browse stuff.... if(syncURL.isEmpty()) syncURL = panel->otherPanel()->virtualPath(); QString relative = QDir(panel->virtualPath().path() + '/').relativeFilePath(url.path()); syncURL.setPath(QDir::cleanPath(syncURL.path() + '/' + relative)); panel->otherPanel()->gui->setTabState(ListPanel::TabState::DEFAULT); otherFunc()->openUrlInternal(syncURL, nameToMakeCurrent, false, false); } openUrlInternal(url, nameToMakeCurrent, false, manuallyEntered); } void ListPanelFunc::immediateOpenUrl(const QUrl &url) { openUrlInternal(url, QString(), true, false); } void ListPanelFunc::openUrlInternal(const QUrl &url, const QString& nameToMakeCurrent, bool immediately, bool manuallyEntered) { const QUrl cleanUrl = cleanPath(url); if (panel->isLocked() && !files()->currentDirectory().matches(cleanUrl, QUrl::StripTrailingSlash)) { panel->_manager->newTab(url); urlManuallyEntered = false; return; } urlManuallyEntered = manuallyEntered; const QString currentItem = history->currentUrl().path() == cleanUrl.path() ? history->currentItem() : nameToMakeCurrent; history->add(cleanUrl, currentItem); if(immediately) doRefresh(); else refresh(); } void ListPanelFunc::refresh() { panel->cancelProgress(); delayTimer.start(0); // to avoid qApp->processEvents() deadlock situaltion } void ListPanelFunc::doRefresh() { delayTimer.stop(); if (_isPaused) { _refreshAfterPaused = true; // simulate refresh panel->slotStartUpdate(true); return; } else { _refreshAfterPaused = false; } const QUrl url = history->currentUrl(); if(!url.isValid()) { panel->slotStartUpdate(true); // refresh the panel urlManuallyEntered = false; return; } panel->cancelProgress(); // if we are not refreshing to current URL const bool isEqualUrl = files()->currentDirectory().matches(url, QUrl::StripTrailingSlash); if (!isEqualUrl) { panel->setCursor(Qt::WaitCursor); panel->view->clearSavedSelection(); } if (panel->fileSystemError) { panel->fileSystemError->hide(); } panel->setNavigatorUrl(url); // may get a new filesystem for this url FileSystem *fileSystem = FileSystemProvider::instance().getFilesystem(url, files()); fileSystem->setParentWindow(krMainWindow); connect(fileSystem, &FileSystem::aboutToOpenDir, &krMtMan, &KMountMan::autoMount, Qt::DirectConnection); if (fileSystem != fileSystemP) { panel->view->setFiles(0); // disconnect older signals disconnect(fileSystemP, 0, panel, 0); fileSystemP->deleteLater(); fileSystemP = fileSystem; // v != 0 so this is safe } else { if (fileSystemP->isRefreshing()) { // TODO remove busy waiting here delayTimer.start(100); /* if filesystem is busy try refreshing later */ return; } } // (re)connect filesystem signals disconnect(files(), 0, panel, 0); connect(files(), &DirListerInterface::scanDone, panel, &ListPanel::slotStartUpdate); connect(files(), &FileSystem::fileSystemInfoChanged, panel, &ListPanel::updateFilesystemStats); connect(files(), &FileSystem::refreshJobStarted, panel, &ListPanel::slotRefreshJobStarted); connect(files(), SIGNAL(error(QString)), panel, SLOT(slotFilesystemError(QString))); panel->view->setFiles(files()); if(!history->currentItem().isEmpty() && isEqualUrl) { // if the url we're refreshing into is the current one, then the // partial refresh will not generate the needed signals to actually allow the // view to use nameToMakeCurrent. do it here instead (patch by Thomas Jarosch) qDebug() << "setting current item=" << history->currentItem(); panel->view->setCurrentItem(history->currentItem()); panel->view->makeItemVisible(panel->view->getCurrentKrViewItem()); } panel->view->setNameToMakeCurrent(history->currentItem()); // workaround for detecting panel deletion while filesystem is refreshing QPointer panelSave = panel; // NOTE: this is blocking. Returns false on error or interruption (cancel requested or panel // was deleted) const bool scanned = fileSystemP->refresh(url); if (scanned) { // update the history and address bar, as the actual url might differ from the one requested history->setCurrentUrl(fileSystemP->currentDirectory()); panel->setNavigatorUrl(fileSystemP->currentDirectory()); } else if (!panelSave) { return; } panel->view->setNameToMakeCurrent(QString()); panel->setCursor(Qt::ArrowCursor); // on local file system change the working directory if (files()->isLocal()) QDir::setCurrent(KrServices::urlToLocalPath(files()->currentDirectory())); // see if the open url operation failed, and if so, // put the attempted url in the navigator bar and let the user change it if (!scanned) { if(isSyncing(url)) panel->otherPanel()->gui->syncBrowseButton->setChecked(false); else if(urlManuallyEntered) { panel->setNavigatorUrl(url); if(panel == ACTIVE_PANEL) panel->editLocation(); } } if(otherFunc()->otherFunc() == this) // not true if our tab is not active otherFunc()->syncURL = QUrl(); urlManuallyEntered = false; refreshActions(); } void ListPanelFunc::setPaused(bool paused) { if (paused == _isPaused) return; _isPaused = paused; // TODO: disable refresh() in local file system when paused if (!_isPaused && _refreshAfterPaused) refresh(); } void ListPanelFunc::redirectLink() { if (!files()->isLocal()) { KMessageBox::sorry(krMainWindow, i18n("You can edit links only on local file systems")); return; } FileItem *fileitem = files()->getFileItem(panel->getCurrentName()); if (!fileitem) return; QString file = fileitem->getUrl().path(); QString currentLink = fileitem->getSymDest(); if (currentLink.isEmpty()) { KMessageBox::sorry(krMainWindow, i18n("The current file is not a link, so it cannot be redirected.")); return; } // ask the user for a new destination bool ok = false; QString newLink = QInputDialog::getText(krMainWindow, i18n("Link Redirection"), i18n("Please enter the new link destination:"), QLineEdit::Normal, currentLink, &ok); // if the user canceled - quit if (!ok || newLink == currentLink) return; // delete the current link if (unlink(file.toLocal8Bit()) == -1) { KMessageBox::sorry(krMainWindow, i18n("Cannot remove old link: %1", file)); return; } // try to create a new symlink if (symlink(newLink.toLocal8Bit(), file.toLocal8Bit()) == -1) { KMessageBox:: /* --=={ Patch by Heiner }==-- */sorry(krMainWindow, i18n("Failed to create a new link: %1", file)); return; } } void ListPanelFunc::krlink(bool sym) { if (!files()->isLocal()) { KMessageBox::sorry(krMainWindow, i18n("You can create links only on local file systems")); return; } QString name = panel->getCurrentName(); // ask the new link name.. bool ok = false; QString linkName = QInputDialog::getText(krMainWindow, i18n("New Link"), i18n("Create a new link to: %1", name), QLineEdit::Normal, name, &ok); // if the user canceled - quit if (!ok || linkName == name) return; // if the name is already taken - quit if (files()->getFileItem(linkName) != 0) { KMessageBox::sorry(krMainWindow, i18n("A folder or a file with this name already exists.")); return; } // make link name and target absolute path if (linkName.left(1) != "/") linkName = files()->currentDirectory().path() + '/' + linkName; name = files()->getUrl(name).path(); if (sym) { if (symlink(name.toLocal8Bit(), linkName.toLocal8Bit()) == -1) KMessageBox::sorry(krMainWindow, i18n("Failed to create a new symlink '%1' to: '%2'", linkName, name)); } else { if (link(name.toLocal8Bit(), linkName.toLocal8Bit()) == -1) KMessageBox::sorry(krMainWindow, i18n("Failed to create a new link '%1' to '%2'", linkName, name)); } } void ListPanelFunc::view() { QString fileName = panel->getCurrentName(); if (fileName.isNull()) return; // if we're trying to view a directory, just exit FileItem *fileitem = files()->getFileItem(fileName); if (!fileitem || fileitem->isDir()) return; if (!fileitem->isReadable()) { KMessageBox::sorry(0, i18n("No permissions to view this file.")); return; } // call KViewer. KrViewer::view(files()->getUrl(fileName)); // nothing more to it! } void ListPanelFunc::viewDlg() { // ask the user for a url to view QUrl dest = KChooseDir::getFile(i18n("Enter a URL to view:"), panel->virtualPath(), panel->virtualPath()); if (dest.isEmpty()) return ; // the user canceled KrViewer::view(dest); // view the file } void ListPanelFunc::terminal() { SLOTS->runTerminal(panel->lastLocalPath()); } void ListPanelFunc::edit() { KFileItem tmp; if (fileToCreate.isEmpty()) { QString name = panel->getCurrentName(); if (name.isNull()) return; fileToCreate = files()->getUrl(name); } tmp = KFileItem(fileToCreate); if (tmp.isDir()) { KMessageBox::sorry(krMainWindow, i18n("You cannot edit a folder")); fileToCreate = QUrl(); return; } if (!tmp.isReadable()) { KMessageBox::sorry(0, i18n("No permissions to edit this file.")); fileToCreate = QUrl(); return; } KrViewer::edit(fileToCreate); fileToCreate = QUrl(); } void ListPanelFunc::editNew() { if(!fileToCreate.isEmpty()) return; // ask the user for the filename to edit fileToCreate = KChooseDir::getFile(i18n("Enter the filename to edit:"), panel->virtualPath(), panel->virtualPath()); if(fileToCreate.isEmpty()) return ; // the user canceled // if the file exists, edit it instead of creating a new one QFile f(fileToCreate.toLocalFile()); if(f.exists()) { edit(); } else { QTemporaryFile *tempFile = new QTemporaryFile; tempFile->open(); KIO::CopyJob *job = KIO::copy(QUrl::fromLocalFile(tempFile->fileName()), fileToCreate); job->setUiDelegate(0); job->setDefaultPermissions(true); connect(job, SIGNAL(result(KJob*)), SLOT(slotFileCreated(KJob*))); connect(job, SIGNAL(result(KJob*)), tempFile, SLOT(deleteLater())); } } void ListPanelFunc::slotFileCreated(KJob *job) { if(!job->error() || job->error() == KIO::ERR_FILE_ALREADY_EXIST) { KrViewer::edit(fileToCreate); if(KIO::upUrl(fileToCreate).matches(panel->virtualPath(), QUrl::StripTrailingSlash)) refresh(); else if(KIO::upUrl(fileToCreate).matches(panel->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)) otherFunc()->refresh(); } else KMessageBox::sorry(krMainWindow, job->errorString()); fileToCreate = QUrl(); } void ListPanelFunc::copyFiles(bool enqueue, bool move) { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety QUrl destination = panel->otherPanel()->virtualPath(); bool fullDestPath = false; if (fileNames.count() == 1 && otherFunc()->files()->type() != FileSystem::FS_VIRTUAL) { FileItem *item = files()->getFileItem(fileNames[0]); if (item && !item->isDir()) { fullDestPath = true; // add original filename to destination destination.setPath(QDir(destination.path()).filePath(item->getUrl().fileName())); } } if (!fullDestPath) { destination = FileSystem::ensureTrailingSlash(destination); } const KConfigGroup group(krConfig, "Advanced"); const bool showDialog = move ? group.readEntry("Confirm Move", _ConfirmMove) : group.readEntry("Confirm Copy", _ConfirmCopy); if (showDialog) { QString operationText; if (move) { operationText = fileNames.count() == 1 ? i18n("Move %1 to:", fileNames.first()) : i18np("Move %1 file to:", "Move %1 files to:", fileNames.count()); } else { operationText = fileNames.count() == 1 ? i18n("Copy %1 to:", fileNames.first()) : i18np("Copy %1 file to:", "Copy %1 files to:", fileNames.count()); } // ask the user for the copy/move dest const KChooseDir::ChooseResult result = KChooseDir::getCopyDir(operationText, destination, panel->virtualPath()); destination = result.url; if (destination.isEmpty()) return ; // the user canceled enqueue = result.enqueue; } const JobMan::StartMode startMode = enqueue && krJobMan->isQueueModeEnabled() ? JobMan::Delay : !enqueue && !krJobMan->isQueueModeEnabled() ? JobMan::Start : JobMan::Enqueue; const QList fileUrls = files()->getUrls(fileNames); if (move) { // after the delete return the cursor to the first unmarked file above the current item panel->prepareToDelete(); } // make sure the user does not overwrite multiple files by mistake if (fileNames.count() > 1) { destination = FileSystem::ensureTrailingSlash(destination); } const KIO::CopyJob::CopyMode mode = move ? KIO::CopyJob::Move : KIO::CopyJob::Copy; FileSystemProvider::instance().startCopyFiles(fileUrls, destination, mode, true, startMode); if(KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { panel->view->saveSelection(); panel->view->unselectAll(); } } // called from SLOTS to begin the renaming process void ListPanelFunc::rename() { panel->view->renameCurrentItem(); } // called by signal itemRenamed() from the view to complete the renaming process void ListPanelFunc::rename(const QString &oldname, const QString &newname) { if (oldname == newname) return ; // do nothing // set current after rename panel->view->setNameToMakeCurrent(newname); // as always - the filesystem do the job files()->rename(oldname, newname); } void ListPanelFunc::mkdir() { // ask the new dir name.. // suggested name is the complete name for the directories // while filenames are suggested without their extension QString suggestedName = panel->getCurrentName(); if (!suggestedName.isEmpty() && !files()->getFileItem(suggestedName)->isDir()) suggestedName = QFileInfo(suggestedName).completeBaseName(); const QString dirName = QInputDialog::getText(krMainWindow, i18n("New folder"), i18n("Folder's name:"), QLineEdit::Normal, suggestedName); const QString firstName = dirName.section('/', 0, 0, QString::SectionIncludeLeadingSep); // if the user canceled or the name was composed of slashes - quit if (!dirName.startsWith('/') && firstName.isEmpty()) { return; } // notify user about existing folder if only single directory was given if (!dirName.contains('/') && files()->getFileItem(firstName)) { // focus the existing directory panel->view->setCurrentItem(firstName); // show error message KMessageBox::sorry(krMainWindow, i18n("A folder or a file with this name already exists.")); return; } // focus new directory when next refresh happens panel->view->setNameToMakeCurrent(firstName); // create new directory (along with underlying directories if necessary) files()->mkDir(dirName); } void ListPanelFunc::defaultOrAlternativeDeleteFiles(bool invert) { const bool trash = KConfigGroup(krConfig, "General").readEntry("Move To Trash", _MoveToTrash); deleteFiles(trash != invert); } void ListPanelFunc::deleteFiles(bool moveToTrash) { if (files()->type() == FileSystem::FS_VIRTUAL && files()->isRoot()) { // only virtual deletion possible removeVirtualFiles(); return; } // first get the selected file names list const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return; // move to trash: only if possible moveToTrash = moveToTrash && files()->canMoveToTrash(fileNames); // now ask the user if he/she is sure: const QList confirmedUrls = confirmDeletion( files()->getUrls(fileNames), moveToTrash, files()->type() == FileSystem::FS_VIRTUAL, false); if (confirmedUrls.isEmpty()) return; // nothing to delete // after the delete return the cursor to the first unmarked // file above the current item; panel->prepareToDelete(); // let the filesystem do the job... QStringList confirmedFileNames; for (QUrl fileUrl : confirmedUrls) { confirmedFileNames.append(fileUrl.fileName()); } files()->deleteFiles(confirmedFileNames, moveToTrash); } QList ListPanelFunc::confirmDeletion(const QList &urls, bool moveToTrash, bool virtualFS, bool showPath) { QStringList files; for (QUrl fileUrl : urls) { files.append(showPath ? fileUrl.toDisplayString(QUrl::PreferLocalFile) : fileUrl.fileName()); } const KConfigGroup advancedGroup(krConfig, "Advanced"); if (advancedGroup.readEntry("Confirm Delete", _ConfirmDelete)) { QString s; // text KGuiItem b; // continue button if (moveToTrash) { s = i18np("Do you really want to move this item to the trash?", "Do you really want to move these %1 items to the trash?", files.count()); b = KGuiItem(i18n("&Trash")); } else if (virtualFS) { s = i18np("Do you really want to delete this item physically (not just " "removing it from the virtual items)?", "Do you really want to delete these %1 items physically (not just " "removing them from the virtual items)?", files.count()); b = KStandardGuiItem::del(); } else { s = i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", files.count()); b = KStandardGuiItem::del(); } // show message // note: i'm using continue and not yes/no because the yes/no has cancel as default button if (KMessageBox::warningContinueCancelList(krMainWindow, s, files, i18n("Warning"), b) != KMessageBox::Continue) { return QList(); } } // we want to warn the user about non empty dir const bool emptyDirVerify = advancedGroup.readEntry("Confirm Unempty Dir", _ConfirmUnemptyDir); QList toDelete; if (emptyDirVerify) { QSet confirmedFiles = urls.toSet(); for (QUrl fileUrl : urls) { if (!fileUrl.isLocalFile()) { continue; // TODO only local fs supported } const QString filePath = fileUrl.toLocalFile(); QFileInfo fileInfo(filePath); if (fileInfo.isDir() && !fileInfo.isSymLink()) { // read local dir... const QDir dir(filePath); if (!dir.entryList(QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot).isEmpty()) { // ...is not empty, ask user const QString fileString = showPath ? filePath : fileUrl.fileName(); const KMessageBox::ButtonCode result = KMessageBox::warningYesNoCancel( krMainWindow, i18n("

Folder %1 is not empty.

", fileString) + (moveToTrash ? i18n("

Skip this one or trash all?

") : i18n("

Skip this one or delete all?

")), QString(), KGuiItem(i18n("&Skip")), KGuiItem(moveToTrash ? i18n("&Trash All") : i18n("&Delete All"))); if (result == KMessageBox::Yes) { confirmedFiles.remove(fileUrl); // skip this dir } else if (result == KMessageBox::No) { break; // accept all remaining } else { return QList(); // cancel } } } } toDelete = confirmedFiles.toList(); } else { toDelete = urls; } return toDelete; } void ListPanelFunc::removeVirtualFiles() { if (files()->type() != FileSystem::FS_VIRTUAL) { qWarning() << "filesystem not virtual"; return; } const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return; const QString text = i18np("Do you really want to delete this virtual item (physical files stay untouched)?", "Do you really want to delete these %1 virtual items (physical files stay " "untouched)?", fileNames.count()); if (KMessageBox::warningContinueCancelList(krMainWindow, text, fileNames, i18n("Warning"), KStandardGuiItem::remove()) != KMessageBox::Continue) return; VirtualFileSystem *fileSystem = static_cast(files()); fileSystem->remove(fileNames); } void ListPanelFunc::goInside(const QString& name) { openFileNameInternal(name, false); } void ListPanelFunc::runCommand(QString cmd) { qDebug() << "command=" << cmd; const QString workdir = panel->virtualPath().isLocalFile() ? panel->virtualPath().path() : QDir::homePath(); if(!KRun::runCommand(cmd, krMainWindow, workdir)) KMessageBox::error(0, i18n("Could not start %1", cmd)); } void ListPanelFunc::runService(const KService &service, QList urls) { qDebug() << "service name=" << service.name(); KIO::DesktopExecParser parser(service, urls); QStringList args = parser.resultingArguments(); if (!args.isEmpty()) runCommand(KShell::joinArgs(args)); else KMessageBox::error(0, i18n("%1 cannot open %2", service.name(), KrServices::toStringList(urls).join(", "))); } void ListPanelFunc::displayOpenWithDialog(QList urls) { // NOTE: we are not using KRun::displayOpenWithDialog() because we want the commands working // directory to be the panel directory KOpenWithDialog dialog(urls, panel); dialog.hideRunInTerminal(); if (dialog.exec()) { KService::Ptr service = dialog.service(); if(!service) service = KService::Ptr(new KService(dialog.text(), dialog.text(), QString())); runService(*service, urls); } } QUrl ListPanelFunc::browsableArchivePath(const QString &filename) { FileItem *fileitem = files()->getFileItem(filename); QUrl url = files()->getUrl(filename); QString mime = fileitem->getMime(); if(url.isLocalFile()) { QString protocol = KrServices::registeredProtocol(mime); if(!protocol.isEmpty()) { url.setScheme(protocol); return url; } } return QUrl(); } // this is done when you double click on a file void ListPanelFunc::execute(const QString& name) { openFileNameInternal(name, true); } void ListPanelFunc::pack() { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety if (fileNames.count() == 0) return ; // nothing to pack // choose the default name QString defaultName = panel->virtualPath().fileName(); if (defaultName.isEmpty()) defaultName = "pack"; if (fileNames.count() == 1) defaultName = fileNames.first(); // ask the user for archive name and packer new PackGUI(defaultName, panel->otherPanel()->virtualPath().toDisplayString(QUrl::PreferLocalFile | QUrl::StripTrailingSlash), fileNames.count(), fileNames.first()); if (PackGUI::type.isEmpty()) { return ; // the user canceled } // check for partial URLs if (!PackGUI::destination.contains(":/") && !PackGUI::destination.startsWith('/')) { PackGUI::destination = panel->virtualPath().toDisplayString() + '/' + PackGUI::destination; } QString destDir = PackGUI::destination; if (!destDir.endsWith('/')) destDir += '/'; bool packToOtherPanel = (destDir == FileSystem::ensureTrailingSlash(panel->otherPanel()->virtualPath()).toDisplayString(QUrl::PreferLocalFile)); QUrl destURL = QUrl::fromUserInput(destDir + PackGUI::filename + '.' + PackGUI::type, QString(), QUrl::AssumeLocalFile); if (destURL.isLocalFile() && QFile::exists(destURL.path())) { QString msg = i18n("

The archive %1.%2 already exists. Do you want to overwrite it?

All data in the previous archive will be lost.

", PackGUI::filename, PackGUI::type); if (PackGUI::type == "zip") { msg = i18n("

The archive %1.%2 already exists. Do you want to overwrite it?

Zip will replace identically named entries in the zip archive or add entries for new names.

", PackGUI::filename, PackGUI::type); } if (KMessageBox::warningContinueCancel(krMainWindow, msg, QString(), KStandardGuiItem::overwrite()) == KMessageBox::Cancel) return ; // stop operation } else if (destURL.scheme() == QStringLiteral("virt")) { KMessageBox::error(krMainWindow, i18n("Cannot pack files onto a virtual destination.")); return; } PackJob * job = PackJob::createPacker(files()->currentDirectory(), destURL, fileNames, PackGUI::type, PackGUI::extraProps); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); if (packToOtherPanel) connect(job, SIGNAL(result(KJob*)), panel->otherPanel()->func, SLOT(refresh())); } void ListPanelFunc::testArchive() { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety TestArchiveJob * job = TestArchiveJob::testArchives(files()->currentDirectory(), fileNames); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); } void ListPanelFunc::unpack() { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety QString s; if (fileNames.count() == 1) s = i18n("Unpack %1 to:", fileNames[0]); else s = i18np("Unpack %1 file to:", "Unpack %1 files to:", fileNames.count()); // ask the user for the copy dest QUrl dest = KChooseDir::getDir(s, panel->otherPanel()->virtualPath(), panel->virtualPath()); if (dest.isEmpty()) return ; // the user canceled bool packToOtherPanel = (dest.matches(panel->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)); UnpackJob * job = UnpackJob::createUnpacker(files()->currentDirectory(), dest, fileNames); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->uiDelegate()->setAutoErrorHandlingEnabled(true); if (packToOtherPanel) connect(job, SIGNAL(result(KJob*)), panel->otherPanel()->func, SLOT(refresh())); } void ListPanelFunc::createChecksum() { if (!panel->func->files()->isLocal()) return; // only local, non-virtual files are supported KrViewItemList items; panel->view->getSelectedKrViewItems(&items); QStringList fileNames; for (KrViewItem *item : items) { FileItem *file = panel->func->getFileItem(item); fileNames.append(file->getUrl().fileName()); } if (fileNames.isEmpty()) return; // nothing selected and no valid current file Checksum::startCreationWizard(panel->virtualPath().toLocalFile(), fileNames); } void ListPanelFunc::matchChecksum() { if (!panel->func->files()->isLocal()) return; // only local, non-virtual files are supported FileItem *currentItem = files()->getFileItem(panel->getCurrentName()); const QString checksumFilePath = currentItem ? currentItem->getUrl().toLocalFile() : QString(); Checksum::startVerifyWizard(panel->virtualPath().toLocalFile(), checksumFilePath); } void ListPanelFunc::calcSpace() { QStringList fileNames; panel->view->getSelectedItems(&fileNames); if (fileNames.isEmpty()) { // current file is ".." dummy file panel->view->selectAllIncludingDirs(); panel->view->getSelectedItems(&fileNames); } SizeCalculator *sizeCalculator = createAndConnectSizeCalculator(files()->getUrls(fileNames)); KrCalcSpaceDialog::showDialog(panel, sizeCalculator); } void ListPanelFunc::quickCalcSpace() { const QString currentName = panel->getCurrentName(); if (currentName.isEmpty()) { // current file is ".." dummy, do a verbose calcSpace calcSpace(); return; } if (!_quickSizeCalculator) { _quickSizeCalculator = createAndConnectSizeCalculator(QList()); panel->connectQuickSizeCalculator(_quickSizeCalculator); } _quickSizeCalculator->add(files()->getUrl(currentName)); } SizeCalculator *ListPanelFunc::createAndConnectSizeCalculator(const QList &urls) { SizeCalculator *sizeCalculator = new SizeCalculator(urls); connect(sizeCalculator, &SizeCalculator::calculated, this, &ListPanelFunc::slotSizeCalculated); connect(sizeCalculator, &SizeCalculator::finished, panel, &ListPanel::slotUpdateTotals); connect(this, &ListPanelFunc::destroyed, sizeCalculator, &SizeCalculator::deleteLater); return sizeCalculator; } void ListPanelFunc::slotSizeCalculated(const QUrl &url, KIO::filesize_t size) { KrViewItem *item = panel->view->findItemByUrl(url); if (!item) return; item->setSize(size); item->redraw(); } void ListPanelFunc::FTPDisconnect() { // you can disconnect only if connected! if (files()->isRemote()) { panel->_actions->actFTPDisconnect->setEnabled(false); panel->view->setNameToMakeCurrent(QString()); openUrl(QUrl::fromLocalFile(panel->lastLocalPath())); } } void ListPanelFunc::newFTPconnection() { QUrl url = KRSpWidgets::newFTP(); // if the user canceled - quit if (url.isEmpty()) return; panel->_actions->actFTPDisconnect->setEnabled(true); qDebug() << "URL=" << url.toDisplayString(); openUrl(url); } void ListPanelFunc::properties() { const QStringList names = panel->getSelectedNames(); if (names.isEmpty()) { return ; // no names... } KFileItemList fileItems; for (const QString name : names) { FileItem *fileitem = files()->getFileItem(name); if (!fileitem) { continue; } fileItems.push_back(KFileItem(fileitem->getEntry(), files()->getUrl(name))); } if (fileItems.isEmpty()) return; // Show the properties dialog KPropertiesDialog *dialog = new KPropertiesDialog(fileItems, krMainWindow); connect(dialog, &KPropertiesDialog::applied, this, &ListPanelFunc::refresh); dialog->show(); } void ListPanelFunc::refreshActions() { panel->updateButtons(); if(ACTIVE_PANEL != panel) return; QString protocol = files()->currentDirectory().scheme(); krRemoteEncoding->setEnabled(protocol == "ftp" || protocol == "sftp" || protocol == "fish" || protocol == "krarc"); //krMultiRename->setEnabled( fileSystemType == FileSystem::FS_NORMAL ); // batch rename //krProperties ->setEnabled( fileSystemType == FileSystem::FS_NORMAL || fileSystemType == FileSystem::FS_FTP ); // file properties /* krUnpack->setEnabled(true); // unpack archive krTest->setEnabled(true); // test archive krSelect->setEnabled(true); // select a group by filter krSelectAll->setEnabled(true); // select all files krUnselect->setEnabled(true); // unselect by filter krUnselectAll->setEnabled( true); // remove all selections krInvert->setEnabled(true); // invert the selection krFTPConnect->setEnabled(true); // connect to an ftp krFTPNew->setEnabled(true); // create a new connection krAllFiles->setEnabled(true); // show all files in list krCustomFiles->setEnabled(true); // show a custom set of files krRoot->setEnabled(true); // go all the way up krExecFiles->setEnabled(true); // show only executables */ panel->_actions->setViewActions[panel->panelType]->setChecked(true); panel->_actions->actFTPDisconnect->setEnabled(files()->isRemote()); // allow disconnecting a network session panel->_actions->actCreateChecksum->setEnabled(files()->isLocal()); panel->_actions->actDirUp->setEnabled(!files()->isRoot()); panel->_actions->actRoot->setEnabled(!panel->virtualPath().matches(QUrl::fromLocalFile(ROOT_DIR), QUrl::StripTrailingSlash)); panel->_actions->actHome->setEnabled(!atHome()); panel->_actions->actHistoryBackward->setEnabled(history->canGoBack()); panel->_actions->actHistoryForward->setEnabled(history->canGoForward()); panel->view->op()->emitRefreshActions(); } FileSystem* ListPanelFunc::files() { if (!fileSystemP) fileSystemP = FileSystemProvider::instance().getFilesystem(QUrl::fromLocalFile(ROOT_DIR)); return fileSystemP; } QUrl ListPanelFunc::virtualDirectory() { return _isPaused ? history->currentUrl() : files()->currentDirectory(); } FileItem *ListPanelFunc::getFileItem(const QString &name) { return files()->getFileItem(name); } FileItem *ListPanelFunc::getFileItem(KrViewItem *item) { return files()->getFileItem(item->name()); } void ListPanelFunc::clipboardChanged(QClipboard::Mode mode) { if (mode == QClipboard::Clipboard && this == copyToClipboardOrigin) { disconnect(QApplication::clipboard(), 0, this, 0); copyToClipboardOrigin = 0; } } void ListPanelFunc::copyToClipboard(bool move) { const QStringList fileNames = panel->getSelectedNames(); if (fileNames.isEmpty()) return ; // safety QList fileUrls = files()->getUrls(fileNames); QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-kde-cutselection", move ? "1" : "0"); mimeData->setUrls(fileUrls); if (copyToClipboardOrigin) disconnect(QApplication::clipboard(), 0, copyToClipboardOrigin, 0); copyToClipboardOrigin = this; QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); connect(QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), this, SLOT(clipboardChanged(QClipboard::Mode))); } void ListPanelFunc::pasteFromClipboard() { QClipboard * cb = QApplication::clipboard(); ListPanelFunc *origin = 0; if (copyToClipboardOrigin) { disconnect(QApplication::clipboard(), 0, copyToClipboardOrigin, 0); origin = copyToClipboardOrigin; copyToClipboardOrigin = 0; } bool move = false; const QMimeData *data = cb->mimeData(); if (data->hasFormat("application/x-kde-cutselection")) { QByteArray a = data->data("application/x-kde-cutselection"); if (!a.isEmpty()) move = (a.at(0) == '1'); // true if 1 } QList urls = data->urls(); if (urls.isEmpty()) return; if(origin && KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { origin->panel->view->saveSelection(); for(KrViewItem *item = origin->panel->view->getFirst(); item != 0; item = origin->panel->view->getNext(item)) { if (urls.contains(item->getFileItem()->getUrl())) item->setSelected(false); } } files()->addFiles(urls, move ? KIO::CopyJob::Move : KIO::CopyJob::Copy); } ListPanelFunc* ListPanelFunc::otherFunc() { return panel->otherPanel()->func; } void ListPanelFunc::historyGotoPos(int pos) { if(history->gotoPos(pos)) refresh(); } void ListPanelFunc::historyBackward() { if(history->goBack()) refresh(); } void ListPanelFunc::historyForward() { if(history->goForward()) refresh(); } void ListPanelFunc::dirUp() { openUrl(KIO::upUrl(files()->currentDirectory()), files()->currentDirectory().fileName()); } void ListPanelFunc::home() { openUrl(QUrl::fromLocalFile(QDir::homePath())); } void ListPanelFunc::root() { openUrl(QUrl::fromLocalFile(ROOT_DIR)); } void ListPanelFunc::cdToOtherPanel() { openUrl(panel->otherPanel()->virtualPath()); } void ListPanelFunc::syncOtherPanel() { otherFunc()->openUrl(panel->virtualPath()); } bool ListPanelFunc::atHome() { return QUrl::fromLocalFile(QDir::homePath()).matches(panel->virtualPath(), QUrl::StripTrailingSlash); } diff --git a/krusader/Panel/panelfunc.h b/krusader/Panel/panelfunc.h index 0ca0d5d8..c9e075b7 100644 --- a/krusader/Panel/panelfunc.h +++ b/krusader/Panel/panelfunc.h @@ -1,178 +1,168 @@ -/*************************************************************************** - panelfunc.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef PANELFUNC_H #define PANELFUNC_H // QtCore #include #include #include // QtGui #include #include #include #include class DirHistoryQueue; class FileItem; class FileSystem; class KrViewItem; class ListPanel; class SizeCalculator; class ListPanelFunc : public QObject { friend class ListPanel; Q_OBJECT public slots: void execute(const QString&); void goInside(const QString&); void openUrl(const QUrl &path, const QString& nameToMakeCurrent = QString(), bool manuallyEntered = false); void rename(const QString &oldname, const QString &newname); // actions void historyBackward(); void historyForward(); void dirUp(); void refresh(); void home(); void root(); void cdToOtherPanel(); void FTPDisconnect(); void newFTPconnection(); void terminal(); void view(); void viewDlg(); void edit(); void editNew(); // create a new textfile and edit it void moveFilesDelayed() { moveFiles(true); } void copyFilesDelayed() { copyFiles(true); } void moveFiles(bool enqueue = false) { copyFiles(enqueue, true); } void copyFiles(bool enqueue = false, bool move = false); /*! * asks the user the new directory name */ void mkdir(); /** Delete or move selected files to trash - depending on user setting. */ void defaultDeleteFiles() { defaultOrAlternativeDeleteFiles(false); } /** Delete or move selected files to trash - inverting the user setting. */ void alternativeDeleteFiles() { defaultOrAlternativeDeleteFiles(true); } /** Delete virtual files or directories in virtual filesystem. */ void removeVirtualFiles(); void rename(); void krlink(bool sym = true); void createChecksum(); void matchChecksum(); void pack(); void unpack(); void testArchive(); /** Calculate the occupied space of the currently selected items and show a dialog. */ void calcSpace(); /** Calculate the occupied space of the current item without dialog. */ void quickCalcSpace(); void properties(); void cut() { copyToClipboard(true); } void copyToClipboard(bool move = false); void pasteFromClipboard(); void syncOtherPanel(); /** Disable refresh if panel is not visible. */ void setPaused(bool paused); public: explicit ListPanelFunc(ListPanel *parent); ~ListPanelFunc(); FileSystem* files(); // return a pointer to the filesystem QUrl virtualDirectory(); // return the current URL (simulated when panel is paused) FileItem* getFileItem(KrViewItem *item); FileItem* getFileItem(const QString& name); void refreshActions(); void redirectLink(); void runService(const KService &service, QList urls); void displayOpenWithDialog(QList urls); QUrl browsableArchivePath(const QString &); void deleteFiles(bool moveToTrash); ListPanelFunc* otherFunc(); bool atHome(); /** Ask user for confirmation before deleting files. Returns only confirmed files.*/ static QList confirmDeletion(const QList &urls, bool moveToTrash, bool virtualFS, bool showPath); protected slots: // Load the current url from history and refresh filesystem and panel to it void doRefresh(); void slotFileCreated(KJob *job); // a file has been created by editNewFile() void historyGotoPos(int pos); void clipboardChanged(QClipboard::Mode mode); // Update the directory size in view void slotSizeCalculated(const QUrl &url, KIO::filesize_t size); protected: QUrl cleanPath(const QUrl &url); bool isSyncing(const QUrl &url); // when externallyExecutable == true, the file can be executed or opened with other software void openFileNameInternal(const QString &name, bool externallyExecutable); void immediateOpenUrl(const QUrl &url); void openUrlInternal(const QUrl &url, const QString& makeCurrent, bool immediately, bool manuallyEntered); void runCommand(QString cmd); ListPanel* panel; // our ListPanel DirHistoryQueue* history; FileSystem* fileSystemP; // pointer to fileSystem. QTimer delayTimer; QUrl syncURL; QUrl fileToCreate; // file that's to be created by editNewFile() bool urlManuallyEntered; static QPointer copyToClipboardOrigin; private: void defaultOrAlternativeDeleteFiles(bool invert); bool getSelectedFiles(QStringList& args); SizeCalculator *createAndConnectSizeCalculator(const QList &urls); bool _isPaused; // do not refresh while panel is not visible bool _refreshAfterPaused; // refresh after not paused anymore QPointer _quickSizeCalculator; }; #endif diff --git a/krusader/Panel/viewactions.cpp b/krusader/Panel/viewactions.cpp index 9fc9d8aa..582f76ad 100644 --- a/krusader/Panel/viewactions.cpp +++ b/krusader/Panel/viewactions.cpp @@ -1,193 +1,183 @@ -/*************************************************************************** - viewactions.cpp - ------------------- -copyright : (C) 2010 by Jan Lepper -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "viewactions.h" #include "PanelView/krview.h" #include "../krmainwindow.h" #include #include ViewActions::ViewActions(QObject *parent, KrMainWindow *mainWindow) : ActionsBase(parent, mainWindow) { // zoom actZoomIn = action(i18n("Zoom In"), "zoom-in", 0, SLOT(zoomIn()), "zoom_in"); actZoomOut = action(i18n("Zoom Out"), "zoom-out", 0, SLOT(zoomOut()), "zoom_out"); actDefaultZoom = action(i18n("Default Zoom"), "zoom-original", 0, SLOT(defaultZoom()), "default_zoom"); // filter action(i18n("&All Files"), 0, Qt::SHIFT + Qt::Key_F10, SLOT(allFilter()), "all files"); //actExecFilter = new QAction( i18n( "&Executables" ), SHIFT + Qt::Key_F11, // SLOTS, SLOT(execFilter()), actionCollection(), "exec files" ); action(i18n("&Custom"), 0, Qt::SHIFT + Qt::Key_F12, SLOT(customFilter()), "custom files"); // selection actSelect = action(i18n("Select &Group..."), "edit-select", Qt::CTRL + Qt::Key_Plus, SLOT(markGroup()), "select group"); actSelectAll = action(i18n("&Select All"), "edit-select-all", Qt::ALT + Qt::Key_Plus, SLOT(markAll()), "select all"); actUnselect = action(i18n("&Unselect Group..."), "kr_unselect", Qt::CTRL + Qt::Key_Minus, SLOT(unmarkGroup()), "unselect group"); actUnselectAll = action(i18n("U&nselect All"), "edit-select-none", Qt::ALT + Qt::Key_Minus, SLOT(unmarkAll()), "unselect all"); actInvert = action(i18n("&Invert Selection"), "edit-select-invert", Qt::ALT + Qt::Key_Asterisk, SLOT(invertSelection()), "invert"); actRestoreSelection = action(i18n("Restore Selection"), 0, 0, SLOT(restoreSelection()), "restore_selection"); actMarkSameBaseName = action(i18n("Select Files with the Same Name"), 0, 0, SLOT(markSameBaseName()), "select_same_base_name"); actMarkSameExtension = action(i18n("Select Files with the Same Extension"), 0, 0, SLOT(markSameExtension()), "select_same_extension"); // other stuff action(i18n("Show View Options Menu"), 0, 0, SLOT(showOptionsMenu()), "show_view_options_menu"); action(i18n("Set Focus to the Panel"), 0, 0, SLOT(focusPanel()), "focus_panel"); action(i18n("Apply settings to other tabs"), 0, 0, SLOT(applySettingsToOthers()), "view_apply_settings_to_others"); actTogglePreviews = toggleAction(i18n("Show Previews"), 0, 0, SLOT(togglePreviews(bool)), "toggle previews"); QAction *actSaveaveDefaultSettings = action(i18n("Save settings as default"), 0, 0, SLOT(saveDefaultSettings()), "view_save_default_settings"); // tooltips actSelect->setToolTip(i18n("Select group")); actSelectAll->setToolTip(i18n("Select all files in the current folder")); actUnselectAll->setToolTip(i18n("Unselect all")); actSaveaveDefaultSettings->setToolTip(i18n("Save settings as default for new instances of this view type")); } inline KrView *ViewActions::view() { return _mainWindow->activeView(); } // zoom void ViewActions::zoomIn() { view()->zoomIn(); } void ViewActions::zoomOut() { view()->zoomOut(); } void ViewActions::defaultZoom() { view()->setDefaultFileIconSize(); } // filter void ViewActions::allFilter() { view()->setFilter(KrViewProperties::All); } #if 0 void ViewActions::execFilter() { view()->setFilter(KrViewProperties::All); } #endif void ViewActions::customFilter() { view()->setFilter(KrViewProperties::Custom); } void ViewActions::showOptionsMenu() { view()->showContextMenu(); } // selection void ViewActions::markAll() { view()->changeSelection(KRQuery("*"), true); } void ViewActions::unmarkAll() { view()->unselectAll(); } void ViewActions::markGroup() { view()->customSelection(true); } void ViewActions::unmarkGroup() { view()->customSelection(false); } void ViewActions::invertSelection() { view()->invertSelection(); } void ViewActions::restoreSelection() { view()->restoreSelection(); } void ViewActions::markSameBaseName() { view()->markSameBaseName(); } void ViewActions::markSameExtension() { view()->markSameExtension(); } // other stuff void ViewActions::saveDefaultSettings() { view()->saveDefaultSettings(); } void ViewActions::applySettingsToOthers() { view()->applySettingsToOthers(); } void ViewActions::focusPanel() { view()->widget()->setFocus(); } void ViewActions::togglePreviews(bool show) { view()->showPreviews(show); } void ViewActions::refreshActions() { actDefaultZoom->setEnabled(view()->defaultFileIconSize() != view()->fileIconSize()); int idx = KrView::iconSizes.indexOf(view()->fileIconSize()); actZoomOut->setEnabled(idx > 0); actZoomIn->setEnabled(idx < (KrView::iconSizes.count() - 1)); actRestoreSelection->setEnabled(view()->canRestoreSelection()); actTogglePreviews->setChecked(view()->previewsShown()); } diff --git a/krusader/Panel/viewactions.h b/krusader/Panel/viewactions.h index 6dde448e..3a695297 100644 --- a/krusader/Panel/viewactions.h +++ b/krusader/Panel/viewactions.h @@ -1,87 +1,76 @@ -/*************************************************************************** - viewactions.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2010 by Jan Lepper - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2010 Jan Lepper * + * Copyright (C) 2010-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef VIEWACTIONS_H #define VIEWACTIONS_H #include "../actionsbase.h" // QtWidgets #include class KrView; class ViewActions : public ActionsBase { Q_OBJECT public: ViewActions(QObject *parent, KrMainWindow *mainWindow); public slots: //zoom void zoomIn(); void zoomOut(); void defaultZoom(); //filter void allFilter(); //void execFilter(); void customFilter(); // selection void markAll(); void unmarkAll(); void markGroup(); void unmarkGroup(); void invertSelection(); void restoreSelection(); void markSameBaseName(); void markSameExtension(); void showOptionsMenu(); void saveDefaultSettings(); void applySettingsToOthers(); void focusPanel(); void togglePreviews(bool show); void refreshActions(); public: QAction *actZoomIn, *actZoomOut, *actDefaultZoom; QAction *actSelect, *actUnselect, *actSelectAll, *actUnselectAll, *actInvert, *actRestoreSelection; QAction *actMarkSameBaseName, *actMarkSameExtension; KToggleAction *actTogglePreviews; protected: KrView *view(); }; #endif // VIEWACTIONS_H diff --git a/krusader/Search/krsearchdialog.cpp b/krusader/Search/krsearchdialog.cpp index 67d6d92b..14dfa683 100644 --- a/krusader/Search/krsearchdialog.cpp +++ b/krusader/Search/krsearchdialog.cpp @@ -1,679 +1,670 @@ -/*************************************************************************** - krsearchdialog.cpp - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krsearchdialog.h" // QtCore #include #include // QtGui #include #include #include #include #include #include // QtWidgets #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 "../kicons.h" #include "../kractions.h" #include "../krglobal.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) {} virtual ~SearchResultContainer() { clear(); } virtual QList fileItems() const Q_DECL_OVERRIDE { return _fileItems; } virtual unsigned long numFileItems() const Q_DECL_OVERRIDE { return _fileItems.count(); } virtual bool isRoot() const Q_DECL_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 = 0; 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(QString profile, QWidget* parent) : QDialog(parent), query(0), searcher(0), isBusy(false), closed(false) { KConfigGroup group(krConfig, "Search"); setWindowTitle(i18n("Krusader::Search")); setWindowIcon(QIcon::fromTheme("system-search")); QGridLayout* searchBaseLayout = new QGridLayout(this); searchBaseLayout->setSpacing(6); searchBaseLayout->setContentsMargins(11, 11, 11, 11); // creating the dialog buttons ( Search, Stop, Close ) QHBoxLayout* 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); QSpacerItem* spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); buttonsLayout->addItem(spacer); mainFeedToListBoxBtn = new QPushButton(this); mainFeedToListBoxBtn->setText(i18n("Feed to listbox")); mainFeedToListBoxBtn->setIcon(QIcon::fromTheme("list-add")); mainFeedToListBoxBtn->setEnabled(false); buttonsLayout->addWidget(mainFeedToListBoxBtn); mainSearchBtn = new QPushButton(this); mainSearchBtn->setText(i18n("Search")); mainSearchBtn->setIcon(QIcon::fromTheme("edit-find")); mainSearchBtn->setDefault(true); buttonsLayout->addWidget(mainSearchBtn); mainStopBtn = new QPushButton(this); mainStopBtn->setEnabled(false); mainStopBtn->setText(i18n("Stop")); mainStopBtn->setIcon(QIcon::fromTheme("process-stop")); buttonsLayout->addWidget(mainStopBtn); mainCloseBtn = new QPushButton(this); mainCloseBtn->setText(i18n("Close")); mainCloseBtn->setIcon(QIcon::fromTheme("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 = (GeneralFilter *)filterTabs->get("GeneralFilter"); QWidget* resultTab = new QWidget(searcherTabs); QGridLayout* resultLayout = new QGridLayout(resultTab); resultLayout->setSpacing(6); resultLayout->setContentsMargins(6, 6, 6, 6); // creating the result tab QHBoxLayout* resultLabelLayout = new QHBoxLayout(); resultLabelLayout->setSpacing(6); resultLabelLayout->setContentsMargins(0, 0, 0, 0); foundLabel = new QLabel(resultTab); QSizePolicy foundpolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); foundpolicy.setHeightForWidth(foundLabel->sizePolicy().hasHeightForWidth()); foundLabel->setSizePolicy(foundpolicy); foundLabel->setFrameShape(QLabel::StyledPanel); foundLabel->setFrameShadow(QLabel::Sunken); foundLabel->setText(i18n("Found 0 matches.")); resultLabelLayout->addWidget(foundLabel); searchingLabel = new KSqueezedTextLabel(resultTab); searchingLabel->setFrameShape(QLabel::StyledPanel); searchingLabel->setFrameShadow(QLabel::Sunken); searchingLabel->setText(""); resultLabelLayout->addWidget(searchingLabel); resultLayout->addLayout(resultLabelLayout, 2, 0); // 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 searchBar = new KrSearchBar(resultView, this); searchBar->hide(); resultLayout->addWidget(searchBar, 1, 0); QHBoxLayout* foundTextLayout = new QHBoxLayout(); foundTextLayout->setSpacing(6); foundTextLayout->setContentsMargins(0, 0, 0, 0); QLabel *l1 = new QLabel(resultTab); QSizePolicy l1policy(QSizePolicy::Minimum, QSizePolicy::Minimum); l1policy.setHeightForWidth(l1->sizePolicy().hasHeightForWidth()); l1->setSizePolicy(l1policy); l1->setFrameShape(QLabel::StyledPanel); l1->setFrameShadow(QLabel::Sunken); l1->setText(i18n("Text found:")); foundTextLayout->addWidget(l1); foundTextLabel = new KrSqueezedTextLabel(resultTab); foundTextLabel->setFrameShape(QLabel::StyledPanel); foundTextLabel->setFrameShadow(QLabel::Sunken); foundTextLabel->setText(""); foundTextLayout->addWidget(foundTextLabel); resultLayout->addLayout(foundTextLayout, 3, 0); searcherTabs->addTab(resultTab, i18n("&Results")); searchBaseLayout->addWidget(searcherTabs, 0, 0); // signals and slots connections connect(mainSearchBtn, SIGNAL(clicked()), this, SLOT(startSearch())); connect(mainStopBtn, SIGNAL(clicked()), this, SLOT(stopSearch())); connect(mainCloseBtn, SIGNAL(clicked()), this, SLOT(closeDialog())); connect(mainFeedToListBoxBtn, SIGNAL(clicked()), this, SLOT(feedToListBox())); connect(profileManager, SIGNAL(loadFromProfile(QString)), filterTabs, SLOT(loadFromProfile(QString))); connect(profileManager, SIGNAL(saveToProfile(QString)), filterTabs, SLOT(saveToProfile(QString))); connect(resultView->op(), SIGNAL(currentChanged(KrViewItem*)), SLOT(currentChanged(KrViewItem*))); connect(resultView->op(), SIGNAL(executed(QString)), SLOT(executed(QString))); connect(resultView->op(), SIGNAL(contextMenu(QPoint)), SLOT(contextMenu(QPoint))); // 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(); // finaly, 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 = 0; delete resultView; resultView = 0; } void KrSearchDialog::closeDialog(bool isAccept) { if(isBusy) { closed = true; return; } // stop the search if it's on-going if (searcher != 0) { delete searcher; searcher = 0; } // 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 = 0; 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 != 0) { delete query; query = 0; } 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."), 0, "searchInArchives"); } // prepare the gui /////////////////////////////////////////////// mainSearchBtn->setEnabled(false); mainCloseBtn->setEnabled(false); mainStopBtn->setEnabled(true); mainFeedToListBoxBtn->setEnabled(false); result->clear(); resultView->setSortMode(KrViewProperties::NoColumn, 0); searchingLabel->setText(""); foundLabel->setText(i18n("Found 0 matches.")); searcherTabs->setCurrentIndex(2); // show the results page foundTextLabel->setText(""); isBusy = true; qApp->processEvents(); // start the search. if (searcher != 0) abort(); searcher = new KRSearchMod(query); connect(searcher, SIGNAL(searching(QString)), searchingLabel, SLOT(setText(QString))); connect(searcher, &KRSearchMod::found, this, &KrSearchDialog::slotFound); connect(searcher, SIGNAL(finished()), this, SLOT(stopSearch())); searcher->start(); isBusy = false; delete searcher; searcher = 0; // gui stuff mainSearchBtn->setEnabled(true); mainCloseBtn->setEnabled(true); mainStopBtn->setEnabled(false); if (result->numFileItems()) mainFeedToListBoxBtn->setEnabled(true); searchingLabel->setText(i18n("Finished searching.")); if (closed) closeDialog(); } void KrSearchDialog::stopSearch() { if (searcher != 0) { searcher->stop(); disconnect(searcher, 0, 0, 0); } } 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 desruction, 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); } else if (e->key() == Qt::Key_F4) { tryPlaceSearchQueryToClipboard(); editCurrent(); return; } else if (e->key() == Qt::Key_F3) { tryPlaceSearchQueryToClipboard(); viewCurrent(); return; } else if (e->key() == Qt::Key_F10) { compareByContent(); return; } else if (KrGlobal::copyShortcut == QKeySequence(e->key() | e->modifiers())) { copyToClipBoard(); return; } } QDialog::keyPressEvent(e); } void KrSearchDialog::editCurrent() { KrViewItem *current = resultView->getCurrentKrViewItem(); if (current) KrViewer::edit(current->getFileItem()->getUrl(), this); } void KrSearchDialog::viewCurrent() { KrViewItem *current = resultView->getCurrentKrViewItem(); if (current) KrViewer::view(current->getFileItem()->getUrl(), this); } void KrSearchDialog::compareByContent() { KrViewItemList list; resultView->getSelectedKrViewItems(&list); 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")); QAction *actView = popup.addAction(i18n("View File (F3)")); QAction *actEdit = popup.addAction(i18n("Edit File (F4)")); QAction *actComp = popup.addAction(i18n("Compare by content (F10)")); if(resultView->numSelected() != 2) actComp->setEnabled(false); QAction *actClip = popup.addAction(i18n("Copy selected to clipboard")); QAction *result = popup.exec(pos); // check out the user's option if (result == actView) viewCurrent(); else if (result == actEdit) editCurrent(); else if (result == actClip) copyToClipBoard(); else if (result == actComp) compareByContent(); } 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) { QString where = KrServices::toStringList(query->searchInDirs()).join(", "); if(query->content().isEmpty()) queryName = i18n("Search results for \"%1\" in %2", query->nameFilter(), where); else queryName = 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) != 0); 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() { QList urls; foreach(FileItem *fileitem, result->fileItems()) urls.push_back(fileitem->getUrl()); if (urls.count() == 0) return; QMimeData *mimeData = new QMimeData; mimeData->setImageData(FL_LOADICON("file")); 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 0a643189..7ac24d6e 100644 --- a/krusader/Search/krsearchdialog.h +++ b/krusader/Search/krsearchdialog.h @@ -1,138 +1,129 @@ -/*************************************************************************** - krsearchdialog.h - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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(QString profile = QString(), QWidget* parent = 0); ~KrSearchDialog(); void prepareGUI(); static KrSearchDialog *SearchDialog; public slots: void startSearch(); void stopSearch(); void feedToListBox(); void copyToClipBoard(); 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 &); virtual void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; virtual void closeEvent(QCloseEvent *e) Q_DECL_OVERRIDE; virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; protected slots: void reject(); private: bool gui2query(); void editCurrent(); void viewCurrent(); void compareByContent(); /** * 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; KRQuery *query; KRSearchMod *searcher; bool isBusy; bool closed; 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/Search/krsearchmod.cpp b/krusader/Search/krsearchmod.cpp index a0aba25b..653d6031 100644 --- a/krusader/Search/krsearchmod.cpp +++ b/krusader/Search/krsearchmod.cpp @@ -1,186 +1,177 @@ -/*************************************************************************** - krsearchmod.cpp - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krsearchmod.h" // QtCore #include #include #include #include // QtWidgets #include #include #include #include "../Archive/krarchandler.h" #include "../FileSystem/defaultfilesystem.h" #include "../FileSystem/fileitem.h" #include "../FileSystem/krpermhandler.h" #include "../FileSystem/krquery.h" #include "../FileSystem/virtualfilesystem.h" #define EVENT_PROCESS_DELAY 250 // milliseconds static const QStringList TAR_TYPES = QStringList() << "tbz" << "tgz" << "tarz" << "tar" << "tlz"; extern KRarcHandler arcHandler; KRSearchMod::KRSearchMod(const KRQuery *query) : m_defaultFileSystem(nullptr), m_virtualFileSystem(nullptr), m_stopSearch(false) { m_query = new KRQuery(*query); connect(m_query, &KRQuery::status, this, &KRSearchMod::searching); connect(m_query, &KRQuery::processEvents, this, &KRSearchMod::slotProcessEvents); } KRSearchMod::~KRSearchMod() { delete m_query; if (m_defaultFileSystem) delete m_defaultFileSystem; if (m_virtualFileSystem) delete m_virtualFileSystem; } void KRSearchMod::start() { m_unScannedUrls.clear(); m_scannedUrls.clear(); m_timer.start(); const QList whereToSearch = m_query->searchInDirs(); // search every dir that needs to be searched for (int i = 0; i < whereToSearch.count(); ++i) scanUrl(whereToSearch[i]); emit finished(); } void KRSearchMod::stop() { m_stopSearch = true; } void KRSearchMod::scanUrl(const QUrl &url) { if (m_stopSearch) return; m_unScannedUrls.push(url); while (!m_unScannedUrls.isEmpty()) { const QUrl url = m_unScannedUrls.pop(); if (m_stopSearch) return; if (m_query->isExcluded(url)) { if (!m_query->searchInDirs().contains(url)) continue; } if (m_scannedUrls.contains(url)) // avoid endless loop continue; m_scannedUrls.push(url); emit searching(url.toDisplayString(QUrl::PreferLocalFile)); scanDirectory(url); } } void KRSearchMod::scanDirectory(const QUrl &url) { FileSystem *fileSystem = getFileSystem(url); // create file items const bool refreshed = fileSystem->scanDir(url); if (!refreshed) { emit error(url); return; } for (FileItem *fileItem : fileSystem->fileItems()) { const QUrl fileUrl = fileItem->getUrl(); if (m_query->isRecursive() && (fileItem->isDir() || (fileItem->isSymLink() && m_query->followLinks()))) { // query search in subdirectory m_unScannedUrls.push(fileUrl); } if (m_query->searchInArchives() && fileUrl.isLocalFile() && KRarcHandler::arcSupported(fileItem->getMime())) { // query search in archive; NOTE: only supported for local files QUrl archiveURL = fileUrl; bool encrypted; const QString type = arcHandler.getType(encrypted, fileUrl.path(), fileItem->getMime()); if (!encrypted) { archiveURL.setScheme(TAR_TYPES.contains(type) ? "tar" : "krarc"); m_unScannedUrls.push(archiveURL); } } if (m_query->match(fileItem)) { // found! emit found(*fileItem, m_query->foundText()); // emitting copy of file item } if (m_timer.elapsed() >= EVENT_PROCESS_DELAY) { qApp->processEvents(); m_timer.start(); if (m_stopSearch) return; } } } FileSystem *KRSearchMod::getFileSystem(const QUrl &url) { FileSystem *fileSystem; if (url.scheme() == QStringLiteral("virt")) { if (!m_virtualFileSystem) m_virtualFileSystem = new VirtualFileSystem(); fileSystem = m_virtualFileSystem; } else { if (!m_defaultFileSystem) m_defaultFileSystem = new DefaultFileSystem(); fileSystem = m_defaultFileSystem; } return fileSystem; } void KRSearchMod::slotProcessEvents(bool &stopped) { qApp->processEvents(); stopped = m_stopSearch; } diff --git a/krusader/Search/krsearchmod.h b/krusader/Search/krsearchmod.h index 88c1a9e4..4a5572f9 100644 --- a/krusader/Search/krsearchmod.h +++ b/krusader/Search/krsearchmod.h @@ -1,91 +1,82 @@ -/*************************************************************************** - krsearchmod.h - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRSEARCHMOD_H #define KRSEARCHMOD_H // QtCore #include #include #include #include #include #include class KRQuery; class FileItem; class FileSystem; class DefaultFileSystem; class VirtualFileSystem; /** * Search for files based on a search query. * * Subdirectories are included if query->isRecursive() is true. */ class KRSearchMod : public QObject { Q_OBJECT public: explicit KRSearchMod(const KRQuery *query); ~KRSearchMod(); void start(); void stop(); private: void scanUrl(const QUrl &url); void scanDirectory(const QUrl &url); FileSystem *getFileSystem(const QUrl &url); signals: void searching(const QString &url); void found(const FileItem &file, const QString &foundText); // NOTE: unused void error(const QUrl &url); void finished(); private slots: void slotProcessEvents(bool &stopped); private: KRQuery *m_query; DefaultFileSystem *m_defaultFileSystem; VirtualFileSystem *m_virtualFileSystem; bool m_stopSearch; QStack m_scannedUrls; QStack m_unScannedUrls; QTime m_timer; }; #endif diff --git a/krusader/Splitter/combiner.cpp b/krusader/Splitter/combiner.cpp index 73c72535..9e352885 100644 --- a/krusader/Splitter/combiner.cpp +++ b/krusader/Splitter/combiner.cpp @@ -1,358 +1,348 @@ -/*************************************************************************** - combiner.cpp - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "combiner.h" #include "../FileSystem/filesystem.h" // QtCore #include #include #include #include #include #include //TODO: delete destination file on error //TODO: cache more than one byte array of data Combiner::Combiner(QWidget* parent, QUrl baseURLIn, QUrl destinationURLIn, bool unixNamingIn) : QProgressDialog(parent, 0), baseURL(baseURLIn), destinationURL(destinationURLIn), hasValidSplitFile(false), fileCounter(0), permissions(-1), receivedSize(0), statJob(0), combineReadJob(0), combineWriteJob(0), unixNaming(unixNamingIn) { crcContext = new CRC32(); splitFile = ""; setMaximum(100); setAutoClose(false); /* don't close or reset the dialog automatically */ setAutoReset(false); setLabelText("Krusader::Combiner"); setWindowModality(Qt::WindowModal); firstFileIs000 = true; //start with this assumption, will set it to false as soon as .000 isn't found } Combiner::~Combiner() { combineAbortJobs(); delete crcContext; } void Combiner::combine() { setWindowTitle(i18n("Krusader::Combining...")); setLabelText(i18n("Combining the file %1...", baseURL.toDisplayString(QUrl::PreferLocalFile))); /* check whether the .crc file exists */ splURL = baseURL.adjusted(QUrl::RemoveFilename); splURL.setPath(splURL.path() + baseURL.fileName() + ".crc"); KFileItem file(splURL); //FIXME: works only for local files - use KIO::stat() instead file.refresh(); if (!file.isReadable()) { int ret = KMessageBox::questionYesNo(0, i18n("The CRC information file (%1) is missing.\n" "Validity checking is impossible without it. Continue combining?", splURL.toDisplayString(QUrl::PreferLocalFile))); if (ret == KMessageBox::No) { emit reject(); return; } statDest(); } else { permissions = file.permissions() | QFile::WriteUser; combineReadJob = KIO::get(splURL, KIO::NoReload, KIO::HideProgressInfo); connect(combineReadJob, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(combineSplitFileDataReceived(KIO::Job*,QByteArray))); connect(combineReadJob, SIGNAL(result(KJob*)), this, SLOT(combineSplitFileFinished(KJob*))); } exec(); } void Combiner::combineSplitFileDataReceived(KIO::Job *, const QByteArray &byteArray) { splitFile += QString(byteArray); } void Combiner::combineSplitFileFinished(KJob *job) { combineReadJob = 0; QString error; if (job->error()) error = i18n("Error at reading the CRC file (%1).", splURL.toDisplayString(QUrl::PreferLocalFile)); else { splitFile.remove('\r'); // Windows compatibility QStringList splitFileContent = splitFile.split('\n'); bool hasFileName = false, hasSize = false, hasCrc = false; for (int i = 0; i != splitFileContent.count(); i++) { int ndx = splitFileContent[i].indexOf('='); if (ndx == -1) continue; QString token = splitFileContent[i].left(ndx).trimmed(); QString value = splitFileContent[i].mid(ndx + 1); if (token == "filename") { expectedFileName = value; hasFileName = true; } else if (token == "size") { //FIXME - don't use c functions !!! sscanf(value.trimmed().toLocal8Bit(), "%llu", &expectedSize); hasSize = true; } if (token == "crc32") { expectedCrcSum = value.trimmed().rightJustified(8, '0'); hasCrc = true; } } if (!hasFileName || !hasSize || !hasCrc) error = i18n("Not a valid CRC file."); else hasValidSplitFile = true; } if (!error.isEmpty()) { int ret = KMessageBox::questionYesNo(0, error + i18n("\nValidity checking is impossible without a good CRC file. Continue combining?")); if (ret == KMessageBox::No) { emit reject(); return; } } statDest(); } void Combiner::statDest() { if (writeURL.isEmpty()) { writeURL = FileSystem::ensureTrailingSlash(destinationURL); if (hasValidSplitFile) writeURL.setPath(writeURL.path() + expectedFileName); else if (unixNaming) writeURL.setPath(writeURL.path() + baseURL.fileName() + ".out"); else writeURL.setPath(writeURL.path() + baseURL.fileName()); } statJob = KIO::stat(writeURL, KIO::StatJob::DestinationSide, 0, KIO::HideProgressInfo); connect(statJob, SIGNAL(result(KJob*)), SLOT(statDestResult(KJob*))); } void Combiner::statDestResult(KJob* job) { statJob = 0; if (job->error()) { if (job->error() == KIO::ERR_DOES_NOT_EXIST) { openNextFile(); } else { static_cast(job)->uiDelegate()->showErrorMessage(); emit reject(); } } else { // destination already exists KIO::RenameDialog_Options mode = static_cast(job)->statResult().isDir() ? KIO::RenameDialog_IsDirectory : KIO::RenameDialog_Overwrite; KIO::RenameDialog dlg(this, i18n("File Already Exists"), QUrl(), writeURL, mode); switch (dlg.exec()) { case KIO::R_OVERWRITE: openNextFile(); break; case KIO::R_RENAME: { writeURL = dlg.newDestUrl(); statDest(); break; } default: emit reject(); } } } void Combiner::openNextFile() { if (unixNaming) { if (readURL.isEmpty()) readURL = baseURL; else { QString name = readURL.fileName(); int pos = name.length() - 1; QChar ch; do { ch = name.at(pos).toLatin1() + 1; if (ch == QChar('Z' + 1)) ch = 'A'; if (ch == QChar('z' + 1)) ch = 'a'; name[ pos ] = ch; pos--; } while (pos >= 0 && ch.toUpper() == QChar('A')); readURL = readURL.adjusted(QUrl::RemoveFilename); readURL.setPath(readURL.path() + name); } } else { QString index("%1"); /* determining the filename */ index = index.arg(fileCounter++).rightJustified(3, '0'); readURL = baseURL.adjusted(QUrl::RemoveFilename); readURL.setPath(readURL.path() + baseURL.fileName() + '.' + index); } /* creating a read job */ combineReadJob = KIO::get(readURL, KIO::NoReload, KIO::HideProgressInfo); connect(combineReadJob, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(combineDataReceived(KIO::Job*,QByteArray))); connect(combineReadJob, SIGNAL(result(KJob*)), this, SLOT(combineReceiveFinished(KJob*))); if (hasValidSplitFile) connect(combineReadJob, SIGNAL(percent(KJob*,ulong)), this, SLOT(combineWritePercent(KJob*,ulong))); } void Combiner::combineDataReceived(KIO::Job *, const QByteArray &byteArray) { if (byteArray.size() == 0) return; crcContext->update((unsigned char *)byteArray.data(), byteArray.size()); transferArray = QByteArray(byteArray.data(), byteArray.length()); receivedSize += byteArray.size(); if (combineWriteJob == 0) { combineWriteJob = KIO::put(writeURL, permissions, KIO::HideProgressInfo | KIO::Overwrite); connect(combineWriteJob, SIGNAL(dataReq(KIO::Job*,QByteArray&)), this, SLOT(combineDataSend(KIO::Job*,QByteArray&))); connect(combineWriteJob, SIGNAL(result(KJob*)), this, SLOT(combineSendFinished(KJob*))); } // continue writing and suspend read job until received data is handed over to the write job combineReadJob->suspend(); combineWriteJob->resume(); } void Combiner::combineReceiveFinished(KJob *job) { combineReadJob = 0; /* KIO automatically deletes the object after Finished signal */ if (job->error()) { if (job->error() == KIO::ERR_DOES_NOT_EXIST) { if (fileCounter == 1) { // .000 file doesn't exist but .001 is still a valid first file firstFileIs000 = false; openNextFile(); } else if (!firstFileIs000 && fileCounter == 2) { // neither .000 nor .001 exist combineAbortJobs(); KMessageBox::error(0, i18n("Cannot open the first split file of %1.", baseURL.toDisplayString(QUrl::PreferLocalFile))); emit reject(); } else { // we've received the last file // write out the remaining part of the file combineWriteJob->resume(); if (hasValidSplitFile) { QString crcResult = QString("%1").arg(crcContext->result(), 0, 16).toUpper().trimmed() .rightJustified(8, '0'); if (receivedSize != expectedSize) error = i18n("Incorrect filesize, the file might have been corrupted."); else if (crcResult != expectedCrcSum.toUpper().trimmed()) error = i18n("Incorrect CRC checksum, the file might have been corrupted."); } } } else { combineAbortJobs(); static_cast(job)->uiDelegate()->showErrorMessage(); emit reject(); } } else openNextFile(); } void Combiner::combineDataSend(KIO::Job *, QByteArray &byteArray) { byteArray = transferArray; transferArray = QByteArray(); if (combineReadJob) { // continue reading and suspend write job until data is available combineReadJob->resume(); combineWriteJob->suspend(); } } void Combiner::combineSendFinished(KJob *job) { combineWriteJob = 0; /* KIO automatically deletes the object after Finished signal */ if (job->error()) { /* any error occurred? */ combineAbortJobs(); static_cast(job)->uiDelegate()->showErrorMessage(); emit reject(); } else if (!error.isEmpty()) { /* was any error message at reading ? */ combineAbortJobs(); /* we cannot write out it in combineReceiveFinished */ KMessageBox::error(0, error); /* because emit accept closes it in this function */ emit reject(); } else emit accept(); } void Combiner::combineAbortJobs() { if (statJob) statJob->kill(KJob::Quietly); if (combineReadJob) combineReadJob->kill(KJob::Quietly); if (combineWriteJob) combineWriteJob->kill(KJob::Quietly); statJob = combineReadJob = combineWriteJob = 0; } void Combiner::combineWritePercent(KJob *, unsigned long) { int percent = (int)((((double)receivedSize / expectedSize) * 100.) + 0.5); setValue(percent); } diff --git a/krusader/Splitter/combiner.h b/krusader/Splitter/combiner.h index 3c494bd9..6420c82d 100644 --- a/krusader/Splitter/combiner.h +++ b/krusader/Splitter/combiner.h @@ -1,99 +1,89 @@ -/*************************************************************************** - combiner.h - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef COMBINER_H #define COMBINER_H // QtCore #include #include // QtWidgets #include #include #include "crc32.h" class Combiner : public QProgressDialog { Q_OBJECT public: Combiner(QWidget* parent, QUrl baseURLIn, QUrl destinationURLIn, bool unixNamingIn = false); ~Combiner(); void combine(); private slots: void statDest(); void statDestResult(KJob* job); void combineSplitFileDataReceived(KIO::Job *, const QByteArray &byteArray); void combineSplitFileFinished(KJob *job); void combineDataReceived(KIO::Job *, const QByteArray &); void combineReceiveFinished(KJob *); void combineDataSend(KIO::Job *, QByteArray &); void combineSendFinished(KJob *); void combineWritePercent(KJob *, unsigned long); private: void openNextFile(); void combineAbortJobs(); QUrl splURL; QUrl readURL; QUrl writeURL; QUrl baseURL; QUrl destinationURL; CRC32 *crcContext; QByteArray transferArray; QString splitFile; QString error; bool hasValidSplitFile; QString expectedFileName; KIO::filesize_t expectedSize; QString expectedCrcSum; int fileCounter; bool firstFileIs000; int permissions; KIO::filesize_t receivedSize; KIO::Job *statJob; KIO::TransferJob *combineReadJob; KIO::TransferJob *combineWriteJob; bool unixNaming; }; #endif /* __COMBINER_H__ */ diff --git a/krusader/Splitter/crc32.cpp b/krusader/Splitter/crc32.cpp index e0bb1c55..83f7b254 100644 --- a/krusader/Splitter/crc32.cpp +++ b/krusader/Splitter/crc32.cpp @@ -1,67 +1,57 @@ -/*************************************************************************** - crc32.cpp - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "crc32.h" #define MASK1 0x00FFFFFF #define MASK2 0xFFFFFFFF #define POLYNOMIAL 0xEDB88320 bool CRC32::crc_initialized = false; unsigned long CRC32::crc_table[ 256 ]; CRC32::CRC32(unsigned long initialValue) { crc_accum = initialValue; if (!crc_initialized) { for (int byte = 0; byte != 256; byte++) { unsigned long data = byte; for (int i = 8; i > 0 ; --i) data = data & 1 ? (data >> 1) ^ POLYNOMIAL : data >> 1; crc_table[ byte ] = data; } crc_initialized = true; } } void CRC32::update(unsigned char *buffer, int bufferLen) { while (bufferLen-- > 0) crc_accum = ((crc_accum >> 8) & MASK1) ^ crc_table[(crc_accum & 0xff) ^ *buffer++ ]; } unsigned long CRC32::result() { return (~crc_accum) & MASK2; } diff --git a/krusader/Splitter/crc32.h b/krusader/Splitter/crc32.h index 4f932093..7ce35018 100644 --- a/krusader/Splitter/crc32.h +++ b/krusader/Splitter/crc32.h @@ -1,48 +1,38 @@ -/*************************************************************************** - crc32.h - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef CRC32_H #define CRC32_H class CRC32 { private: unsigned long crc_accum; static unsigned long crc_table[ 256 ]; static bool crc_initialized; public: explicit CRC32(unsigned long initialValue = (unsigned long) - 1); void update(unsigned char *buffer, int bufferLen); unsigned long result(); }; #endif /* __CRC32_H__ */ diff --git a/krusader/Splitter/splitter.cpp b/krusader/Splitter/splitter.cpp index 69d40408..2c0c602f 100644 --- a/krusader/Splitter/splitter.cpp +++ b/krusader/Splitter/splitter.cpp @@ -1,310 +1,300 @@ -/*************************************************************************** - splitter.cpp - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "splitter.h" #include "../FileSystem/filesystem.h" // QtCore #include // QtWidgets #include #include #include #include #include #include Splitter::Splitter(QWidget* parent, QUrl fileNameIn, QUrl destinationDirIn, bool overWriteIn) : QProgressDialog(parent, 0), fileName(fileNameIn), destinationDir(destinationDirIn), splitSize(0), permissions(0), overwrite(overWriteIn), fileNumber(0), outputFileRemaining(0), receivedSize(0), crcContext(new CRC32()), statJob(0), splitReadJob(0), splitWriteJob(0) { setMaximum(100); setAutoClose(false); /* don't close or reset the dialog automatically */ setAutoReset(false); setLabelText("Krusader::Splitter"); setWindowModality(Qt::WindowModal); } Splitter::~Splitter() { splitAbortJobs(); delete crcContext; } void Splitter::split(KIO::filesize_t splitSizeIn) { Q_ASSERT(!splitReadJob); Q_ASSERT(!splitWriteJob); Q_ASSERT(!fileNumber); Q_ASSERT(!receivedSize); Q_ASSERT(!outputFileRemaining); splitReadJob = splitWriteJob = 0; fileNumber = receivedSize = outputFileRemaining = 0; splitSize = splitSizeIn; KFileItem file(fileName); file.refresh(); //FIXME: works only for local files - use KIO::stat() instead permissions = file.permissions() | QFile::WriteUser; setWindowTitle(i18n("Krusader::Splitting...")); setLabelText(i18n("Splitting the file %1...", fileName.toDisplayString(QUrl::PreferLocalFile))); if (file.isDir()) { KMessageBox::error(0, i18n("Cannot split a folder.")); return; } splitReadJob = KIO::get(fileName, KIO::NoReload, KIO::HideProgressInfo); connect(splitReadJob, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(splitDataReceived(KIO::Job*,QByteArray))); connect(splitReadJob, SIGNAL(result(KJob*)), this, SLOT(splitReceiveFinished(KJob*))); connect(splitReadJob, SIGNAL(percent(KJob*,ulong)), this, SLOT(splitReceivePercent(KJob*,ulong))); exec(); } void Splitter::splitDataReceived(KIO::Job *, const QByteArray &byteArray) { Q_ASSERT(!transferArray.length()); // transfer buffer must be empty if (byteArray.size() == 0) return; crcContext->update((unsigned char *)byteArray.data(), byteArray.size()); receivedSize += byteArray.size(); if (!splitWriteJob) nextOutputFile(); transferArray = QByteArray(byteArray.data(), byteArray.length()); // suspend read job until transfer buffer is handed to the write job splitReadJob->suspend(); if (splitWriteJob) splitWriteJob->resume(); } void Splitter::splitReceiveFinished(KJob *job) { splitReadJob = 0; /* KIO automatically deletes the object after Finished signal */ if (splitWriteJob) splitWriteJob->resume(); // finish writing the output if (job->error()) { /* any error occurred? */ splitAbortJobs(); KMessageBox::error(0, i18n("Error reading file %1: %2", fileName.toDisplayString(QUrl::PreferLocalFile), job->errorString())); emit reject(); return; } QString crcResult = QString("%1").arg(crcContext->result(), 0, 16).toUpper().trimmed() .rightJustified(8, '0'); splitInfoFileContent = QString("filename=%1\n").arg(fileName.fileName()) + QString("size=%1\n") .arg(KIO::number(receivedSize)) + QString("crc32=%1\n") .arg(crcResult); } void Splitter::splitReceivePercent(KJob *, unsigned long percent) { setValue(percent); } void Splitter::nextOutputFile() { Q_ASSERT(!outputFileRemaining); fileNumber++; outputFileRemaining = splitSize; QString index("%1"); /* making the split filename */ index = index.arg(fileNumber).rightJustified(3, '0'); QString outFileName = fileName.fileName() + '.' + index; writeURL = destinationDir; writeURL = writeURL.adjusted(QUrl::StripTrailingSlash); writeURL.setPath(writeURL.path() + '/' + (outFileName)); if (overwrite) openOutputFile(); else { statJob = KIO::stat(writeURL, KIO::StatJob::DestinationSide, 0, KIO::HideProgressInfo); connect(statJob, SIGNAL(result(KJob*)), SLOT(statOutputFileResult(KJob*))); } } void Splitter::statOutputFileResult(KJob* job) { statJob = 0; if (job->error()) { if (job->error() == KIO::ERR_DOES_NOT_EXIST) openOutputFile(); else { static_cast(job)->uiDelegate()->showErrorMessage(); emit reject(); } } else { // destination already exists KIO::RenameDialog dlg(this, i18n("File Already Exists"), QUrl(), writeURL, static_cast(KIO::M_MULTI | KIO::M_OVERWRITE | KIO::M_NORENAME)); switch (dlg.exec()) { case KIO::R_OVERWRITE: openOutputFile(); break; case KIO::R_OVERWRITE_ALL: overwrite = true; openOutputFile(); break; default: emit reject(); } } } void Splitter::openOutputFile() { // create write job splitWriteJob = KIO::put(writeURL, permissions, KIO::HideProgressInfo | KIO::Overwrite); connect(splitWriteJob, SIGNAL(dataReq(KIO::Job*,QByteArray&)), this, SLOT(splitDataSend(KIO::Job*,QByteArray&))); connect(splitWriteJob, SIGNAL(result(KJob*)), this, SLOT(splitSendFinished(KJob*))); } void Splitter::splitDataSend(KIO::Job *, QByteArray &byteArray) { KIO::filesize_t bufferLen = transferArray.size(); if (!outputFileRemaining) { // current output file needs to be closed ? byteArray = QByteArray(); // giving empty buffer which indicates closing } else if (bufferLen > outputFileRemaining) { // maximum length reached ? byteArray = QByteArray(transferArray.data(), outputFileRemaining); transferArray = QByteArray(transferArray.data() + outputFileRemaining, bufferLen - outputFileRemaining); outputFileRemaining = 0; } else { outputFileRemaining -= bufferLen; // write the whole buffer to the output file byteArray = transferArray; transferArray = QByteArray(); if (splitReadJob) { // suspend write job until transfer buffer is filled or the read job is finished splitWriteJob->suspend(); splitReadJob->resume(); } // else: write job continues until transfer buffer is empty } } void Splitter::splitSendFinished(KJob *job) { splitWriteJob = 0; /* KIO automatically deletes the object after Finished signal */ if (job->error()) { /* any error occurred? */ splitAbortJobs(); KMessageBox::error(0, i18n("Error writing file %1: %2", writeURL.toDisplayString(QUrl::PreferLocalFile), job->errorString())); emit reject(); return; } if (transferArray.size()) /* any data remained in the transfer buffer? */ nextOutputFile(); else if (splitReadJob) splitReadJob->resume(); else { // read job is finished and transfer buffer is empty -> splitting is finished /* writing the split information file out */ writeURL = destinationDir; writeURL = writeURL.adjusted(QUrl::StripTrailingSlash); writeURL.setPath(writeURL.path() + '/' + (fileName.fileName() + ".crc")); splitWriteJob = KIO::put(writeURL, permissions, KIO::HideProgressInfo | KIO::Overwrite); connect(splitWriteJob, SIGNAL(dataReq(KIO::Job*,QByteArray&)), this, SLOT(splitFileSend(KIO::Job*,QByteArray&))); connect(splitWriteJob, SIGNAL(result(KJob*)), this, SLOT(splitFileFinished(KJob*))); } } void Splitter::splitAbortJobs() { if (statJob) statJob->kill(KJob::Quietly); if (splitReadJob) splitReadJob->kill(KJob::Quietly); if (splitWriteJob) splitWriteJob->kill(KJob::Quietly); splitReadJob = splitWriteJob = 0; } void Splitter::splitFileSend(KIO::Job *, QByteArray &byteArray) { byteArray = splitInfoFileContent.toLocal8Bit(); splitInfoFileContent = ""; } void Splitter::splitFileFinished(KJob *job) { splitWriteJob = 0; /* KIO automatically deletes the object after Finished signal */ if (job->error()) { /* any error occurred? */ KMessageBox::error(0, i18n("Error writing file %1: %2", writeURL.toDisplayString(QUrl::PreferLocalFile), job->errorString())); emit reject(); return; } emit accept(); } diff --git a/krusader/Splitter/splitter.h b/krusader/Splitter/splitter.h index e49ec33a..1ceab761 100644 --- a/krusader/Splitter/splitter.h +++ b/krusader/Splitter/splitter.h @@ -1,92 +1,82 @@ -/*************************************************************************** - splitter.h - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef SPLITTER_H #define SPLITTER_H // QtCore #include #include // QtWidgets #include #include #include "crc32.h" class Splitter : public QProgressDialog { Q_OBJECT public: Splitter(QWidget* parent, QUrl fileNameIn, QUrl destinationDirIn, bool overWriteIn); ~Splitter(); void split(KIO::filesize_t splitSizeIn); private slots: void splitDataReceived(KIO::Job *, const QByteArray &); void splitDataSend(KIO::Job *, QByteArray &); void splitSendFinished(KJob *); void splitReceiveFinished(KJob *); void splitReceivePercent(KJob *, unsigned long); void splitFileSend(KIO::Job *, QByteArray &); void splitFileFinished(KJob *); void statOutputFileResult(KJob* job); private: void splitAbortJobs(); void nextOutputFile(); void openOutputFile(); // parameters QUrl fileName; QUrl destinationDir; KIO::filesize_t splitSize; int permissions; bool overwrite; // current split file stuff int fileNumber; QUrl writeURL; // how much can still be written to the current output file KIO::filesize_t outputFileRemaining; QByteArray transferArray; KIO::filesize_t receivedSize; QString splitInfoFileContent; CRC32 *crcContext; KIO::Job *statJob; KIO::TransferJob *splitReadJob; KIO::TransferJob *splitWriteJob; }; #endif /* __SPLITTER_H__ */ diff --git a/krusader/Splitter/splittergui.cpp b/krusader/Splitter/splittergui.cpp index d8902530..71165ae5 100644 --- a/krusader/Splitter/splittergui.cpp +++ b/krusader/Splitter/splittergui.cpp @@ -1,275 +1,265 @@ -/*************************************************************************** - splittergui.cpp - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "splittergui.h" #include "../FileSystem/filesystem.h" // QtCore #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct SplitterGUI::PredefinedDevice { PredefinedDevice(QString name, KIO::filesize_t capacity) : name(name), capacity(capacity) {} PredefinedDevice(const PredefinedDevice &other) : name(other.name), capacity(other.capacity) {} PredefinedDevice &operator=(const PredefinedDevice &other); QString name; KIO::filesize_t capacity; }; const QList &SplitterGUI::predefinedDevices() { static QList list; if(!list.count()) { list << PredefinedDevice(i18n("1.44 MB (3.5\")"), 1457664); list << PredefinedDevice(i18n("1.2 MB (5.25\")"), 1213952); list << PredefinedDevice(i18n("720 kB (3.5\")"), 730112); list << PredefinedDevice(i18n("360 kB (5.25\")"), 362496); list << PredefinedDevice(i18n("100 MB (ZIP)"), 100431872); list << PredefinedDevice(i18n("250 MB (ZIP)"), 250331136); list << PredefinedDevice(i18n("650 MB (CD-R)"), 650*0x100000); list << PredefinedDevice(i18n("700 MB (CD-R)"), 700*0x100000); } return list; }; SplitterGUI::SplitterGUI(QWidget* parent, QUrl fileURL, QUrl defaultDir) : QDialog(parent), userDefinedSize(0x100000), lastSelectedDevice(-1), division(1) { setModal(true); QGridLayout *grid = new QGridLayout(this); grid->setSpacing(6); grid->setContentsMargins(11, 11, 11, 11); QLabel *splitterLabel = new QLabel(this); splitterLabel->setText(i18n("Split the file %1 to folder:", fileURL.toDisplayString(QUrl::PreferLocalFile))); splitterLabel->setMinimumWidth(400); grid->addWidget(splitterLabel, 0 , 0); urlReq = new KUrlRequester(this); urlReq->setUrl(defaultDir); urlReq->setMode(KFile::Directory); grid->addWidget(urlReq, 1 , 0); QWidget *splitSizeLine = new QWidget(this); QHBoxLayout * splitSizeLineLayout = new QHBoxLayout; splitSizeLineLayout->setContentsMargins(0, 0, 0, 0); splitSizeLine->setLayout(splitSizeLineLayout); deviceCombo = new QComboBox(splitSizeLine); for (int i = 0; i != predefinedDevices().count(); i++) deviceCombo->addItem(predefinedDevices()[i].name); deviceCombo->addItem(i18n("User Defined")); splitSizeLineLayout->addWidget(deviceCombo); QLabel *spacer = new QLabel(splitSizeLine); spacer->setText(" "); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); splitSizeLineLayout->addWidget(spacer); QLabel *bytesPerFile = new QLabel(splitSizeLine); bytesPerFile->setText(i18n("Max file size:")); splitSizeLineLayout->addWidget(bytesPerFile); spinBox = new QDoubleSpinBox(splitSizeLine); spinBox->setMaximum(9999999999.0); spinBox->setMinimumWidth(85); spinBox->setEnabled(false); splitSizeLineLayout->addWidget(spinBox); sizeCombo = new QComboBox(splitSizeLine); sizeCombo->addItem(i18n("Byte")); sizeCombo->addItem(i18n("kByte")); sizeCombo->addItem(i18n("MByte")); sizeCombo->addItem(i18n("GByte")); splitSizeLineLayout->addWidget(sizeCombo); grid->addWidget(splitSizeLine, 2 , 0); overwriteCb = new QCheckBox(i18n("Overwrite files without confirmation"), this); grid->addWidget(overwriteCb, 3, 0); QFrame *separator = new QFrame(this); separator->setFrameStyle(QFrame::HLine | QFrame::Sunken); separator->setFixedHeight(separator->sizeHint().height()); grid->addWidget(separator, 4 , 0); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("&Split")); grid->addWidget(buttonBox, 5 , 0); setWindowTitle(i18n("Krusader::Splitter")); KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Splitter")); overwriteCb->setChecked(cfg.readEntry("OverWriteFiles", false)); connect(sizeCombo, SIGNAL(activated(int)), this, SLOT(sizeComboActivated(int))); connect(deviceCombo, SIGNAL(activated(int)), this, SLOT(predefinedComboActivated(int))); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(buttonBox , SIGNAL(accepted()), this, SLOT(splitPressed())); predefinedComboActivated(0); } SplitterGUI::~SplitterGUI() { KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Splitter")); cfg.writeEntry("OverWriteFiles", overwriteCb->isChecked()); } KIO::filesize_t SplitterGUI::getSplitSize() { if(deviceCombo->currentIndex() < predefinedDevices().count()) // predefined size selected return predefinedDevices()[deviceCombo->currentIndex()].capacity; // user defined size selected return spinBox->value() * division; } bool SplitterGUI::overWriteFiles() { return overwriteCb->isChecked(); } void SplitterGUI::sizeComboActivated(int item) { KIO::filesize_t prevDivision = division; switch (item) { case 0: division = 1; /* byte */ break; case 1: division = 0x400; /* kbyte */ break; case 2: division = 0x100000; /* Mbyte */ break; case 3: division = 0x40000000; /* Gbyte */ break; } double value; if(deviceCombo->currentIndex() < predefinedDevices().count()) // predefined size selected value = (double)predefinedDevices()[deviceCombo->currentIndex()].capacity / division; else { // use defined size selected value = (double)(spinBox->value() * prevDivision) / division; if(value < 1) value = 1; } spinBox->setValue(value); } void SplitterGUI::predefinedComboActivated(int item) { if(item == lastSelectedDevice) return; KIO::filesize_t capacity = userDefinedSize; if (lastSelectedDevice == predefinedDevices().count()) // user defined was selected previously userDefinedSize = spinBox->value() * division; // remember user defined size if(item < predefinedDevices().count()) { // predefined size selected capacity = predefinedDevices()[item].capacity; spinBox->setEnabled(false); } else // user defined size selected spinBox->setEnabled(true); //qDebug() << capacity; if (capacity >= 0x40000000) { /* Gbyte */ sizeCombo->setCurrentIndex(3); division = 0x40000000; } else if (capacity >= 0x100000) { /* Mbyte */ sizeCombo->setCurrentIndex(2); division = 0x100000; } else if (capacity >= 0x400) { /* kbyte */ sizeCombo->setCurrentIndex(1); division = 0x400; } else { sizeCombo->setCurrentIndex(0); /* byte */ division = 1; } spinBox->setValue((double)capacity / division); lastSelectedDevice = item; } void SplitterGUI::splitPressed() { if (!urlReq->url().isValid()) { KMessageBox::error(this, i18n("The folder path URL is malformed.")); return; } if(getSplitSize() > 0) emit accept(); } void SplitterGUI::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Enter : case Qt::Key_Return : emit splitPressed(); return; default: QDialog::keyPressEvent(e); } } diff --git a/krusader/Splitter/splittergui.h b/krusader/Splitter/splittergui.h index df788a71..deb048ce 100644 --- a/krusader/Splitter/splittergui.h +++ b/krusader/Splitter/splittergui.h @@ -1,84 +1,74 @@ -/*************************************************************************** - splittergui.h - description - ------------------- - copyright : (C) 2003 by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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, QUrl fileURL, QUrl defaultDir); ~SplitterGUI(); 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: virtual void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; }; #endif /* __SPLITTERGUI_H__ */ diff --git a/krusader/Synchronizer/feedtolistboxdialog.cpp b/krusader/Synchronizer/feedtolistboxdialog.cpp index 36d428db..bf47b965 100644 --- a/krusader/Synchronizer/feedtolistboxdialog.cpp +++ b/krusader/Synchronizer/feedtolistboxdialog.cpp @@ -1,216 +1,206 @@ -/*************************************************************************** - feedtolistboxdialog.cpp - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "feedtolistboxdialog.h" #include "synchronizer.h" #include "synchronizergui.h" #include "../FileSystem/filesystem.h" #include "../FileSystem/virtualfilesystem.h" #include "../krglobal.h" #include "../krusaderview.h" #include "../panelmanager.h" // QtWidgets #include #include #include #include #include #include #include #include #include #define S_LEFT 0 #define S_RIGHT 1 #define S_BOTH 2 FeedToListBoxDialog::FeedToListBoxDialog(QWidget *parent, Synchronizer *sync, QTreeWidget *syncL, bool equOK) : QDialog(parent), synchronizer(sync), syncList(syncL), equalAllowed(equOK), accepted(false) { setWindowTitle(i18n("Krusader::Feed to listbox")); setWindowModality(Qt::WindowModal); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); // autodetecting the parameters int selectedNum = 0; int itemNum = 0; int leftExistingNum = 0; int rightExistingNum = 0; QTreeWidgetItemIterator it(syncList); while (*it) { SynchronizerGUI::SyncViewItem *item = (SynchronizerGUI::SyncViewItem *) * it; SynchronizerFileItem *syncItem = item->synchronizerItemRef(); if (syncItem && syncItem->isMarked()) { if (item->isSelected() || syncItem->task() != TT_EQUALS || equalAllowed) { itemNum++; if (item->isSelected()) selectedNum++; if (syncItem->existsInLeft()) leftExistingNum++; if (syncItem->existsInRight()) rightExistingNum++; } } it++; } if (itemNum == 0) { hide(); KMessageBox::error(parent, i18n("No elements to feed.")); return; } // guessing the collection name VirtualFileSystem virtFilesystem; if (!virtFilesystem.scanDir(QUrl("virt:/"))) return; KConfigGroup group(krConfig, "Synchronize"); int listBoxNum = group.readEntry("Feed To Listbox Counter", 1); QString queryName; do { queryName = i18n("Synchronize results") + QString(" %1").arg(listBoxNum++); } while (virtFilesystem.getFileItem(queryName) != 0); group.writeEntry("Feed To Listbox Counter", listBoxNum); // creating the widget QLabel *label = new QLabel(i18n("Here you can name the file collection"), this); mainLayout->addWidget(label); lineEdit = new QLineEdit(this); lineEdit->setText(queryName); lineEdit->setClearButtonEnabled(true); lineEdit->selectAll(); mainLayout->addWidget(lineEdit); QHBoxLayout * hbox = new QHBoxLayout; QLabel *label2 = new QLabel(i18n("Side to feed:"), this); label2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); hbox->addWidget(label2); sideCombo = new QComboBox(this); sideCombo->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sideCombo->addItem(i18n("Left")); sideCombo->addItem(i18n("Right")); sideCombo->addItem(i18n("Both")); hbox->addWidget(sideCombo); if (leftExistingNum == 0) { sideCombo->setCurrentIndex(1); sideCombo->setEnabled(false); } else if (rightExistingNum == 0) { sideCombo->setCurrentIndex(0); sideCombo->setEnabled(false); } else sideCombo->setCurrentIndex(2); QFrame *line = new QFrame(this); line->setFrameStyle(QFrame::VLine | QFrame::Sunken); line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); hbox->addWidget(line); cbSelected = new QCheckBox(i18n("Selected files only"), this); cbSelected->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); cbSelected->setEnabled(selectedNum != 0); cbSelected->setChecked(selectedNum != 0); hbox->addWidget(cbSelected); mainLayout->addLayout(hbox); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); mainLayout->addWidget(buttonBox); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, SIGNAL(accepted()), SLOT(slotOk())); connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); exec(); } void FeedToListBoxDialog::slotOk() { int side = sideCombo->currentIndex(); bool selected = cbSelected->isChecked(); QString name = lineEdit->text(); QList urlList; QTreeWidgetItemIterator it(syncList); for (;*it; it++) { SynchronizerGUI::SyncViewItem *item = (SynchronizerGUI::SyncViewItem *) * it; SynchronizerFileItem *syncItem = item->synchronizerItemRef(); if (!syncItem || !syncItem->isMarked()) continue; if (selected && !item->isSelected()) continue; if (!equalAllowed && syncItem->task() == TT_EQUALS && (!selected || !item->isSelected())) continue; if ((side == S_BOTH || side == S_LEFT) && syncItem->existsInLeft()) { QString leftDirName = syncItem->leftDirectory().isEmpty() ? "" : syncItem->leftDirectory() + '/'; QUrl leftURL = Synchronizer::fsUrl(synchronizer->leftBaseDirectory() + leftDirName + syncItem->leftName()); urlList.push_back(leftURL); } if ((side == S_BOTH || side == S_RIGHT) && syncItem->existsInRight()) { QString rightDirName = syncItem->rightDirectory().isEmpty() ? "" : syncItem->rightDirectory() + '/'; QUrl leftURL = Synchronizer::fsUrl(synchronizer->rightBaseDirectory() + rightDirName + syncItem->rightName()); urlList.push_back(leftURL); } } QUrl url = QUrl(QString("virt:/") + name); VirtualFileSystem virtFilesystem; if (!virtFilesystem.refresh(url)) { // create directory if it does not exist KMessageBox::error(parentWidget(), i18n("Cannot open %1.", url.toDisplayString())); return; } virtFilesystem.addFiles(urlList); ACTIVE_MNG->slotNewTab(url); accepted = true; accept(); } diff --git a/krusader/Synchronizer/feedtolistboxdialog.h b/krusader/Synchronizer/feedtolistboxdialog.h index d055a26c..2165eb39 100644 --- a/krusader/Synchronizer/feedtolistboxdialog.h +++ b/krusader/Synchronizer/feedtolistboxdialog.h @@ -1,68 +1,58 @@ -/*************************************************************************** - feedtolistboxdialog.h - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef FEEDTOLISTBOXDIALOG_H #define FEEDTOLISTBOXDIALOG_H // QtWidgets #include class Synchronizer; class QCheckBox; class QLineEdit; class QComboBox; class QTreeWidget; class FeedToListBoxDialog : public QDialog { Q_OBJECT public: FeedToListBoxDialog(QWidget*, Synchronizer *, QTreeWidget *, bool); virtual ~FeedToListBoxDialog() {} bool isAccepted() { return accepted; } protected slots: void slotOk(); private: Synchronizer * synchronizer; QTreeWidget * syncList; QCheckBox * cbSelected; QLineEdit * lineEdit; QComboBox * sideCombo; bool equalAllowed; bool accepted; }; #endif /* __FEED_TO_LISTBOX_DIALOG__ */ diff --git a/krusader/Synchronizer/synchronizedialog.cpp b/krusader/Synchronizer/synchronizedialog.cpp index 7ce4cab1..b3e4f505 100644 --- a/krusader/Synchronizer/synchronizedialog.cpp +++ b/krusader/Synchronizer/synchronizedialog.cpp @@ -1,213 +1,203 @@ -/*************************************************************************** - synchronizedialog.cpp - description - ------------------- - copyright : (C) 2003 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "synchronizedialog.h" #include "../FileSystem/krpermhandler.h" #include "../krglobal.h" #include "../defaults.h" // QtWidgets #include #include #include #include #include SynchronizeDialog::SynchronizeDialog(QWidget* parent, Synchronizer *sync, int pleftCopyNr, KIO::filesize_t pleftCopySize, int prightCopyNr, KIO::filesize_t prightCopySize, int pdeleteNr, KIO::filesize_t pdeleteSize, int parThreads) : QDialog(parent), synchronizer(sync), leftCopyNr(pleftCopyNr), leftCopySize(pleftCopySize), rightCopyNr(prightCopyNr), rightCopySize(prightCopySize), deleteNr(pdeleteNr), deleteSize(pdeleteSize), parallelThreads(parThreads), isPause(true), syncStarted(false) { setWindowTitle(i18n("Krusader::Synchronize")); setModal(true); QVBoxLayout *layout = new QVBoxLayout(this); layout->setContentsMargins(11, 11, 11, 11); layout->setSpacing(6); cbRightToLeft = new QCheckBox(i18np("Right to left: Copy 1 file", "Right to left: Copy %1 files", leftCopyNr) + ' ' + i18np("(1 byte)", "(%1 bytes)", KRpermHandler::parseSize(leftCopySize).trimmed().toInt()), this); cbRightToLeft->setChecked(leftCopyNr != 0); cbRightToLeft->setEnabled(leftCopyNr != 0); layout->addWidget(cbRightToLeft); lbRightToLeft = new QLabel(i18np("\tReady: %2/1 file, %3/%4", "\tReady: %2/%1 files, %3/%4", leftCopyNr, 0, 0, KRpermHandler::parseSize(leftCopySize).trimmed()), this); lbRightToLeft->setEnabled(leftCopyNr != 0); layout->addWidget(lbRightToLeft); cbLeftToRight = new QCheckBox(i18np("Left to right: Copy 1 file", "Left to right: Copy %1 files", rightCopyNr) + ' ' + i18np("(1 byte)", "(%1 bytes)", KRpermHandler::parseSize(rightCopySize).trimmed().toInt()), this); cbLeftToRight->setChecked(rightCopyNr != 0); cbLeftToRight->setEnabled(rightCopyNr != 0); layout->addWidget(cbLeftToRight); lbLeftToRight = new QLabel(i18np("\tReady: %2/1 file, %3/%4", "\tReady: %2/%1 files, %3/%4", rightCopyNr, 0, 0, KRpermHandler::parseSize(rightCopySize).trimmed()), this); lbLeftToRight->setEnabled(rightCopyNr != 0); layout->addWidget(lbLeftToRight); cbDeletable = new QCheckBox(i18np("Left: Delete 1 file", "Left: Delete %1 files", deleteNr) + ' ' + i18np("(1 byte)", "(%1 bytes)", KRpermHandler::parseSize(deleteSize).trimmed().toInt()), this); cbDeletable->setChecked(deleteNr != 0); cbDeletable->setEnabled(deleteNr != 0); layout->addWidget(cbDeletable); lbDeletable = new QLabel(i18np("\tReady: %2/1 file, %3/%4", "\tReady: %2/%1 files, %3/%4", deleteNr, 0, 0, KRpermHandler::parseSize(deleteSize).trimmed()), this); lbDeletable->setEnabled(deleteNr != 0); layout->addWidget(lbDeletable); progress = new QProgressBar(this); progress->setMaximum(1000); progress->setMinimum(0); progress->setValue(0); progress->setMinimumWidth(400); layout->addWidget(progress); QWidget *hboxWidget = new QWidget(this); QHBoxLayout * hbox = new QHBoxLayout(hboxWidget); hbox->setSpacing(6); cbOverwrite = new QCheckBox(i18n("Confirm overwrites"), this); KConfigGroup group(krConfig, "Synchronize"); cbOverwrite->setChecked(group.readEntry("Confirm overwrites", _ConfirmOverWrites)); layout->addWidget(cbOverwrite); QSpacerItem* spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hbox->addItem(spacer); btnStart = new QPushButton(hboxWidget); btnStart->setText(i18n("&Start")); btnStart->setIcon(QIcon::fromTheme("media-playback-start")); hbox->addWidget(btnStart); btnPause = new QPushButton(hboxWidget); btnPause->setEnabled(false); btnPause->setText(i18n("&Pause")); btnPause->setIcon(QIcon::fromTheme("media-playback-pause")); hbox->addWidget(btnPause); QPushButton *btnClose = new QPushButton(hboxWidget); btnClose->setText(i18n("&Close")); btnClose->setIcon(QIcon::fromTheme("dialog-close")); hbox->addWidget(btnClose); layout->addWidget(hboxWidget); connect(btnStart, SIGNAL(clicked()), this, SLOT(startSynchronization())); connect(btnPause, SIGNAL(clicked()), this, SLOT(pauseOrResume())); connect(btnClose, SIGNAL(clicked()), this, SLOT(reject())); exec(); } SynchronizeDialog::~SynchronizeDialog() { KConfigGroup group(krConfig, "Synchronize"); group.writeEntry("Confirm overwrites", cbOverwrite->isChecked()); } void SynchronizeDialog::startSynchronization() { btnStart->setEnabled(false); btnPause->setEnabled(syncStarted = true); connect(synchronizer, SIGNAL(synchronizationFinished()), this, SLOT(synchronizationFinished())); connect(synchronizer, SIGNAL(processedSizes(int,KIO::filesize_t,int,KIO::filesize_t,int,KIO::filesize_t)), this, SLOT(processedSizes(int,KIO::filesize_t,int,KIO::filesize_t,int,KIO::filesize_t))); connect(synchronizer, SIGNAL(pauseAccepted()), this, SLOT(pauseAccepted())); if (!cbRightToLeft->isChecked()) leftCopySize = 0; if (!cbLeftToRight->isChecked()) rightCopySize = 0; if (!cbDeletable->isChecked()) deleteSize = 0; synchronizer->synchronize(this, cbRightToLeft->isChecked(), cbLeftToRight->isChecked(), cbDeletable->isChecked(), !cbOverwrite->isChecked(), parallelThreads); } void SynchronizeDialog::synchronizationFinished() { QDialog::reject(); } void SynchronizeDialog::processedSizes(int leftNr, KIO::filesize_t leftSize, int rightNr, KIO::filesize_t rightSize, int delNr, KIO::filesize_t delSize) { lbRightToLeft->setText(i18np("\tReady: %2/1 file, %3/%4", "\tReady: %2/%1 files, %3/%4", leftCopyNr, leftNr, KRpermHandler::parseSize(leftSize).trimmed(), KRpermHandler::parseSize(leftCopySize).trimmed())); lbLeftToRight->setText(i18np("\tReady: %2/1 file, %3/%4", "\tReady: %2/%1 files, %3/%4", rightCopyNr, rightNr, KRpermHandler::parseSize(rightSize).trimmed(), KRpermHandler::parseSize(rightCopySize).trimmed())); lbDeletable->setText(i18np("\tReady: %2/1 file, %3/%4", "\tReady: %2/%1 files, %3/%4", deleteNr, delNr, KRpermHandler::parseSize(delSize).trimmed(), KRpermHandler::parseSize(deleteSize).trimmed())); KIO::filesize_t totalSum = leftCopySize + rightCopySize + deleteSize; KIO::filesize_t processedSum = leftSize + rightSize + delSize; if (totalSum == 0) totalSum++; progress->setValue((int)(((double)processedSum / (double)totalSum)*1000)); } void SynchronizeDialog::pauseOrResume() { if (isPause) { btnPause->setEnabled(false); synchronizer->pause(); } else { btnPause->setText(i18n("Pause")); synchronizer->resume(); isPause = true; } } void SynchronizeDialog::pauseAccepted() { btnPause->setText(i18n("Resume")); btnPause->setEnabled(true); isPause = false; } diff --git a/krusader/Synchronizer/synchronizedialog.h b/krusader/Synchronizer/synchronizedialog.h index 9347ae67..283ada57 100644 --- a/krusader/Synchronizer/synchronizedialog.h +++ b/krusader/Synchronizer/synchronizedialog.h @@ -1,94 +1,84 @@ -/*************************************************************************** - synchronizedialog.h - description - ------------------- - copyright : (C) 2003 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef SYNCHRONIZEDIALOG_H #define SYNCHRONIZEDIALOG_H // QtWidgets #include #include #include #include #include #include "synchronizer.h" class SynchronizeDialog : QDialog { Q_OBJECT public: SynchronizeDialog(QWidget*, Synchronizer *sync, int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t, int); ~SynchronizeDialog(); inline bool wasSyncronizationStarted() { return syncStarted; } public slots: void startSynchronization(); void synchronizationFinished(); void processedSizes(int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t); void pauseOrResume(); void pauseAccepted(); private: QProgressBar *progress; QCheckBox *cbRightToLeft; QCheckBox *cbLeftToRight; QCheckBox *cbDeletable; QLabel *lbRightToLeft; QLabel *lbLeftToRight; QLabel *lbDeletable; QCheckBox *cbOverwrite; QPushButton *btnStart; QPushButton *btnPause; Synchronizer *synchronizer; int leftCopyNr; KIO::filesize_t leftCopySize; int rightCopyNr; KIO::filesize_t rightCopySize; int deleteNr; KIO::filesize_t deleteSize; int parallelThreads; bool isPause; bool syncStarted; }; #endif /* __SYNCHRONIZE_DIALOG__ */ diff --git a/krusader/Synchronizer/synchronizer.cpp b/krusader/Synchronizer/synchronizer.cpp index 27133e2c..ff0756fc 100644 --- a/krusader/Synchronizer/synchronizer.cpp +++ b/krusader/Synchronizer/synchronizer.cpp @@ -1,1453 +1,1443 @@ -/*************************************************************************** - synchronizer.cpp - description - ------------------- - copyright : (C) 2003 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "synchronizer.h" #include "synchronizerdirlist.h" #include "../krglobal.h" #include "../krservices.h" #include "../FileSystem/filesystem.h" #include "../FileSystem/krquery.h" #include // QtCore #include #include #include #include #include #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_POSIX_ACL #include #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS #include #endif #endif #define DISPLAY_UPDATE_PERIOD 2 Synchronizer::Synchronizer() : displayUpdateCount(0), markEquals(true), markDiffers(true), markCopyToLeft(true), markCopyToRight(true), markDeletable(true), stack(), jobMap(), receivedMap(), parentWidget(0), resultListIt(resultList) { } Synchronizer::~Synchronizer() { clearLists(); } QUrl Synchronizer::fsUrl(QString strUrl) { QUrl result = QUrl::fromUserInput(strUrl, QString(), QUrl::AssumeLocalFile); return KrServices::escapeFileUrl(result); } void Synchronizer::clearLists() { QListIterator i1(resultList); while (i1.hasNext()) delete i1.next(); resultList.clear(); QListIterator i2(stack); while (i2.hasNext()) delete i2.next(); stack.clear(); temporaryList.clear(); } void Synchronizer::reset() { displayUpdateCount = 0; markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = true; stopped = false; recurseSubDirs = followSymLinks = ignoreDate = asymmetric = cmpByContent = ignoreCase = autoScroll = false; markEquals = markDiffers = markCopyToLeft = markCopyToRight = markDeletable = markDuplicates = markSingles = false; leftCopyEnabled = rightCopyEnabled = deleteEnabled = overWrite = autoSkip = paused = false; leftCopyNr = rightCopyNr = deleteNr = 0; leftCopySize = rightCopySize = deleteSize = 0; comparedDirs = fileCount = 0; leftBaseDir.clear(); rightBaseDir.clear(); clearLists(); } int Synchronizer::compare(QString leftURL, QString rightURL, KRQuery *query, bool subDirs, bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase, bool autoSc, QStringList &selFiles, int equThres, int timeOffs, int parThreads, bool hiddenFiles) { clearLists(); recurseSubDirs = subDirs; followSymLinks = symLinks; ignoreDate = igDate; asymmetric = asymm; cmpByContent = cmpByCnt; autoScroll = autoSc; ignoreCase = igCase; selectedFiles = selFiles; equalsThreshold = equThres; timeOffset = timeOffs; parallelThreads = parThreads; ignoreHidden = hiddenFiles; stopped = false; this->query = query; leftURL = KUrlCompletion::replacedPath(leftURL, true, true); rightURL = KUrlCompletion::replacedPath(rightURL, true, true); if (!leftURL.endsWith('/')) leftURL += '/'; if (!rightURL.endsWith('/')) rightURL += '/'; excludedPaths = KrServices::toStringList(query->dontSearchInDirs()); for (int i = 0; i != excludedPaths.count(); i++) if (excludedPaths[ i ].endsWith('/')) excludedPaths[ i ].truncate(excludedPaths[ i ].length() - 1); comparedDirs = fileCount = 0; stack.append(new CompareTask(0, leftBaseDir = leftURL, rightBaseDir = rightURL, "", "", ignoreHidden)); compareLoop(); QListIterator it(temporaryList); while (it.hasNext()) { SynchronizerFileItem * item = it.next(); if (item->isTemporary()) delete item; } temporaryList.clear(); if (!autoScroll) refresh(true); emit statusInfo(i18n("Number of files: %1", fileCount)); return fileCount; } void Synchronizer::compareLoop() { while (!stopped && !stack.isEmpty()) { for (int thread = 0; thread < (int)stack.count() && thread < parallelThreads; thread++) { SynchronizerTask * entry = stack.at(thread); if (entry->state() == ST_STATE_NEW) entry->start(parentWidget); if (entry->inherits("CompareTask")) { if (entry->state() == ST_STATE_READY) { CompareTask *ctentry = (CompareTask *) entry; if (ctentry->isDuplicate()) compareDirectory(ctentry->parent(), ctentry->leftDirList(), ctentry->rightDirList(), ctentry->leftDir(), ctentry->rightDir()); else addSingleDirectory(ctentry->parent(), ctentry->dirList(), ctentry->dir(), ctentry->isLeft()); } if (entry->state() == ST_STATE_READY || entry->state() == ST_STATE_ERROR) comparedDirs++; } switch (entry->state()) { case ST_STATE_STATUS: emit statusInfo(entry->status()); break; case ST_STATE_READY: case ST_STATE_ERROR: emit statusInfo(i18n("Number of compared folders: %1", comparedDirs)); stack.removeAll(entry); delete entry; continue; default: break; } } if (!stack.isEmpty()) qApp->processEvents(); } QListIterator it(stack); while (it.hasNext()) delete it.next(); stack.clear(); } void Synchronizer::compareDirectory(SynchronizerFileItem *parent, SynchronizerDirList * left_directory, SynchronizerDirList * right_directory, const QString &leftDir, const QString &rightDir) { const QString &leftURL = left_directory->url(); const QString &rightURL = right_directory->url(); FileItem *left_file; FileItem *right_file; QString file_name; bool checkIfSelected = false; if (leftDir.isEmpty() && rightDir.isEmpty() && selectedFiles.count()) checkIfSelected = true; /* walking through in the left directory */ for (left_file = left_directory->first(); left_file != 0 && !stopped; left_file = left_directory->next()) { if (isDir(left_file)) continue; file_name = left_file->getName(); if (checkIfSelected && !selectedFiles.contains(file_name)) continue; if (!query->match(left_file)) continue; if ((right_file = right_directory->search(file_name, ignoreCase)) == 0) addLeftOnlyItem(parent, file_name, leftDir, left_file->getSize(), left_file->getTime_t(), readLink(left_file), left_file->getOwner(), left_file->getGroup(), left_file->getMode(), left_file->getACL()); else { if (isDir(right_file)) continue; addDuplicateItem(parent, file_name, right_file->getName(), leftDir, rightDir, left_file->getSize(), right_file->getSize(), left_file->getTime_t(), right_file->getTime_t(), readLink(left_file), readLink(right_file), left_file->getOwner(), right_file->getOwner(), left_file->getGroup(), right_file->getGroup(), left_file->getMode(), right_file->getMode(), left_file->getACL(), right_file->getACL()); } } /* walking through in the right directory */ for (right_file = right_directory->first(); right_file != 0 && !stopped; right_file = right_directory->next()) { if (isDir(right_file)) continue; file_name = right_file->getName(); if (checkIfSelected && !selectedFiles.contains(file_name)) continue; if (!query->match(right_file)) continue; if (left_directory->search(file_name, ignoreCase) == 0) addRightOnlyItem(parent, file_name, rightDir, right_file->getSize(), right_file->getTime_t(), readLink(right_file), right_file->getOwner(), right_file->getGroup(), right_file->getMode(), right_file->getACL()); } /* walking through the subdirectories */ if (recurseSubDirs) { for (left_file = left_directory->first(); left_file != 0 && !stopped; left_file = left_directory->next()) { if (left_file->isDir() && (followSymLinks || !left_file->isSymLink())) { QString left_file_name = left_file->getName(); if (checkIfSelected && !selectedFiles.contains(left_file_name)) continue; if (excludedPaths.contains(leftDir.isEmpty() ? left_file_name : leftDir + '/' + left_file_name)) continue; if (!query->matchDirName(left_file_name)) continue; if ((right_file = right_directory->search(left_file_name, ignoreCase)) == 0) { SynchronizerFileItem *me = addLeftOnlyItem(parent, left_file_name, leftDir, 0, left_file->getTime_t(), readLink(left_file), left_file->getOwner(), left_file->getGroup(), left_file->getMode(), left_file->getACL(), true, !query->match(left_file)); stack.append(new CompareTask(me, leftURL + left_file_name + '/', leftDir.isEmpty() ? left_file_name : leftDir + '/' + left_file_name, true, ignoreHidden)); } else { QString right_file_name = right_file->getName(); SynchronizerFileItem *me = addDuplicateItem(parent, left_file_name, right_file_name, leftDir, rightDir, 0, 0, left_file->getTime_t(), right_file->getTime_t(), readLink(left_file), readLink(right_file), left_file->getOwner(), right_file->getOwner(), left_file->getGroup(), right_file->getGroup(), left_file->getMode(), right_file->getMode(), left_file->getACL(), right_file->getACL(), true, !query->match(left_file)); stack.append(new CompareTask(me, leftURL + left_file_name + '/', rightURL + right_file_name + '/', leftDir.isEmpty() ? left_file_name : leftDir + '/' + left_file_name, rightDir.isEmpty() ? right_file_name : rightDir + '/' + right_file_name, ignoreHidden)); } } } /* walking through the right side subdirectories */ for (right_file = right_directory->first(); right_file != 0 && !stopped; right_file = right_directory->next()) { if (right_file->isDir() && (followSymLinks || !right_file->isSymLink())) { file_name = right_file->getName(); if (checkIfSelected && !selectedFiles.contains(file_name)) continue; if (excludedPaths.contains(rightDir.isEmpty() ? file_name : rightDir + '/' + file_name)) continue; if (!query->matchDirName(file_name)) continue; if (left_directory->search(file_name, ignoreCase) == 0) { SynchronizerFileItem *me = addRightOnlyItem(parent, file_name, rightDir, 0, right_file->getTime_t(), readLink(right_file), right_file->getOwner(), right_file->getGroup(), right_file->getMode(), right_file->getACL(), true, !query->match(right_file)); stack.append(new CompareTask(me, rightURL + file_name + '/', rightDir.isEmpty() ? file_name : rightDir + '/' + file_name, false, ignoreHidden)); } } } } } QString Synchronizer::getTaskTypeName(TaskType taskType) { static QString names[] = {"=", "!=", "<-", "->", "DEL", "?", "?", "?", "?", "?"}; return names[taskType]; } SynchronizerFileItem * Synchronizer::addItem(SynchronizerFileItem *parent, const QString &leftFile, const QString &rightFile, const QString &leftDir, const QString &rightDir, bool existsLeft, bool existsRight, KIO::filesize_t leftSize, KIO::filesize_t rightSize, time_t leftDate, time_t rightDate, const QString &leftLink, const QString &rightLink, const QString &leftOwner, const QString &rightOwner, const QString &leftGroup, const QString &rightGroup, mode_t leftMode, mode_t rightMode, const QString &leftACL, const QString &rightACL, TaskType tsk, bool isDir, bool isTemp) { bool marked = autoScroll ? !isTemp && isMarked(tsk, existsLeft && existsRight) : false; SynchronizerFileItem *item = new SynchronizerFileItem(leftFile, rightFile, leftDir, rightDir, marked, existsLeft, existsRight, leftSize, rightSize, leftDate, rightDate, leftLink, rightLink, leftOwner, rightOwner, leftGroup, rightGroup, leftMode, rightMode, leftACL, rightACL, tsk, isDir, isTemp, parent); if (!isTemp) { while (parent && parent->isTemporary()) setPermanent(parent); bool doRefresh = false; if (marked) { fileCount++; if (autoScroll && markParentDirectories(item)) doRefresh = true; } resultList.append(item); emit comparedFileData(item); if (doRefresh) refresh(true); if (marked && (displayUpdateCount++ % DISPLAY_UPDATE_PERIOD == (DISPLAY_UPDATE_PERIOD - 1))) qApp->processEvents(); } else temporaryList.append(item); return item; } void Synchronizer::compareContentResult(SynchronizerFileItem * item, bool res) { item->compareContentResult(res); bool marked = autoScroll ? isMarked(item->task(), item->existsInLeft() && item->existsInRight()) : false; item->setMarked(marked); if (marked) { markParentDirectories(item); fileCount++; emit markChanged(item, true); } } void Synchronizer::setPermanent(SynchronizerFileItem *item) { if (item->parent() && item->parent()->isTemporary()) setPermanent(item->parent()); item->setPermanent(); resultList.append(item); emit comparedFileData(item); } SynchronizerFileItem * Synchronizer::addLeftOnlyItem(SynchronizerFileItem *parent, const QString &file_name, const QString &dir, KIO::filesize_t size, time_t date, const QString &link, const QString &owner, const QString &group, mode_t mode, const QString &acl, bool isDir, bool isTemp) { return addItem(parent, file_name, file_name, dir, dir, true, false, size, 0, date, 0, link, QString(), owner, QString(), group, QString(), mode, (mode_t) - 1, acl, QString(), asymmetric ? TT_DELETE : TT_COPY_TO_RIGHT, isDir, isTemp); } SynchronizerFileItem * Synchronizer::addRightOnlyItem(SynchronizerFileItem *parent, const QString &file_name, const QString &dir, KIO::filesize_t size, time_t date, const QString &link, const QString &owner, const QString &group, mode_t mode, const QString &acl, bool isDir, bool isTemp) { return addItem(parent, file_name, file_name, dir, dir, false, true, 0, size, 0, date, QString(), link, QString(), owner, QString(), group, (mode_t) - 1, mode, QString(), acl, TT_COPY_TO_LEFT, isDir, isTemp); } SynchronizerFileItem * Synchronizer::addDuplicateItem(SynchronizerFileItem *parent, const QString &leftName, const QString &rightName, const QString &leftDir, const QString &rightDir, KIO::filesize_t leftSize, KIO::filesize_t rightSize, time_t leftDate, time_t rightDate, const QString &leftLink, const QString &rightLink, const QString &leftOwner, const QString &rightOwner, const QString &leftGroup, const QString &rightGroup, mode_t leftMode, mode_t rightMode, const QString &leftACL, const QString &rightACL, bool isDir, bool isTemp) { TaskType task; int checkedRightDate = rightDate - timeOffset; int uncertain = 0; do { if (isDir) { task = TT_EQUALS; break; } if (leftSize == rightSize) { if (!leftLink.isNull() || !rightLink.isNull()) { if (leftLink == rightLink) { task = TT_EQUALS; break; } } else if (cmpByContent) uncertain = TT_UNKNOWN; else { if (ignoreDate || leftDate == checkedRightDate) { task = TT_EQUALS; break; } time_t diff = (leftDate > checkedRightDate) ? leftDate - checkedRightDate : checkedRightDate - leftDate; if (diff <= equalsThreshold) { task = TT_EQUALS; break; } } } if (asymmetric) task = TT_COPY_TO_LEFT; else if (ignoreDate) task = TT_DIFFERS; else if (leftDate > checkedRightDate) task = TT_COPY_TO_RIGHT; else if (leftDate < checkedRightDate) task = TT_COPY_TO_LEFT; else task = TT_DIFFERS; } while (false); SynchronizerFileItem * item = addItem(parent, leftName, rightName, leftDir, rightDir, true, true, leftSize, rightSize, leftDate, rightDate, leftLink, rightLink, leftOwner, rightOwner, leftGroup, rightGroup, leftMode, rightMode, leftACL, rightACL, (TaskType)(task + uncertain), isDir, isTemp); if (uncertain == TT_UNKNOWN) { QUrl leftURL = Synchronizer::fsUrl(leftDir.isEmpty() ? leftBaseDir + leftName : leftBaseDir + leftDir + '/' + leftName); QUrl rightURL = Synchronizer::fsUrl(rightDir.isEmpty() ? rightBaseDir + rightName : rightBaseDir + rightDir + '/' + rightName); stack.append(new CompareContentTask(this, item, leftURL, rightURL, leftSize)); } return item; } void Synchronizer::addSingleDirectory(SynchronizerFileItem *parent, SynchronizerDirList *directory, const QString &dirName, bool isLeft) { const QString &url = directory->url(); FileItem *file; QString file_name; /* walking through the directory files */ for (file = directory->first(); file != 0 && !stopped; file = directory->next()) { if (isDir(file)) continue; file_name = file->getName(); if (!query->match(file)) continue; if (isLeft) addLeftOnlyItem(parent, file_name, dirName, file->getSize(), file->getTime_t(), readLink(file), file->getOwner(), file->getGroup(), file->getMode(), file->getACL()); else addRightOnlyItem(parent, file_name, dirName, file->getSize(), file->getTime_t(), readLink(file), file->getOwner(), file->getGroup(), file->getMode(), file->getACL()); } /* walking through the subdirectories */ for (file = directory->first(); file != 0 && !stopped; file = directory->next()) { if (file->isDir() && (followSymLinks || !file->isSymLink())) { file_name = file->getName(); if (excludedPaths.contains(dirName.isEmpty() ? file_name : dirName + '/' + file_name)) continue; if (!query->matchDirName(file_name)) continue; SynchronizerFileItem *me; if (isLeft) me = addLeftOnlyItem(parent, file_name, dirName, 0, file->getTime_t(), readLink(file), file->getOwner(), file->getGroup(), file->getMode(), file->getACL(), true, !query->match(file)); else me = addRightOnlyItem(parent, file_name, dirName, 0, file->getTime_t(), readLink(file), file->getOwner(), file->getGroup(), file->getMode(), file->getACL(), true, !query->match(file)); stack.append(new CompareTask(me, url + file_name + '/', dirName.isEmpty() ? file_name : dirName + '/' + file_name, isLeft, ignoreHidden)); } } } void Synchronizer::setMarkFlags(bool left, bool equal, bool differs, bool right, bool dup, bool sing, bool del) { markEquals = equal; markDiffers = differs; markCopyToLeft = left; markCopyToRight = right; markDeletable = del; markDuplicates = dup; markSingles = sing; } bool Synchronizer::isMarked(TaskType task, bool isDuplicate) { if ((isDuplicate && !markDuplicates) || (!isDuplicate && !markSingles)) return false; switch (task) { case TT_EQUALS: return markEquals; case TT_DIFFERS: return markDiffers; case TT_COPY_TO_LEFT: return markCopyToLeft; case TT_COPY_TO_RIGHT: return markCopyToRight; case TT_DELETE: return markDeletable; default: return false; } } bool Synchronizer::markParentDirectories(SynchronizerFileItem *item) { if (item->parent() == 0 || item->parent()->isMarked()) return false; markParentDirectories(item->parent()); item->parent()->setMarked(true); fileCount++; emit markChanged(item->parent(), false); return true; } int Synchronizer::refresh(bool nostatus) { fileCount = 0; QListIterator it(resultList); while (it.hasNext()) { SynchronizerFileItem * item = it.next(); bool marked = isMarked(item->task(), item->existsInLeft() && item->existsInRight()); item->setMarked(marked); if (marked) { markParentDirectories(item); fileCount++; } } it.toFront(); while (it.hasNext()) { SynchronizerFileItem * item = it.next(); emit markChanged(item, false); } if (!nostatus) emit statusInfo(i18n("Number of files: %1", fileCount)); return fileCount; } void Synchronizer::operate(SynchronizerFileItem *item, void (*executeOperation)(SynchronizerFileItem *)) { executeOperation(item); if (item->isDir()) { QString leftDirName = (item->leftDirectory().isEmpty()) ? item->leftName() : item->leftDirectory() + '/' + item->leftName(); QString rightDirName = (item->rightDirectory().isEmpty()) ? item->rightName() : item->rightDirectory() + '/' + item->rightName(); QListIterator it(resultList); while (it.hasNext()) { SynchronizerFileItem * item = it.next(); if (item->leftDirectory() == leftDirName || item->leftDirectory().startsWith(leftDirName + '/') || item->rightDirectory() == rightDirName || item->rightDirectory().startsWith(rightDirName + '/')) executeOperation(item); } } } void Synchronizer::excludeOperation(SynchronizerFileItem *item) { item->setTask(TT_DIFFERS); } void Synchronizer::exclude(SynchronizerFileItem *item) { if (!item->parent() || item->parent()->task() != TT_DELETE) operate(item, excludeOperation); /* exclude only if the parent task is not DEL */ } void Synchronizer::restoreOperation(SynchronizerFileItem *item) { item->restoreOriginalTask(); } void Synchronizer::restore(SynchronizerFileItem *item) { operate(item, restoreOperation); while ((item = item->parent()) != 0) /* in case of restore, the parent directories */ { /* must be changed for being consistent */ if (item->task() != TT_DIFFERS) break; if (item->originalTask() == TT_DELETE) /* if the parent original task is delete */ break; /* don't touch it */ item->restoreOriginalTask(); /* restore */ } } void Synchronizer::reverseDirectionOperation(SynchronizerFileItem *item) { if (item->existsInRight() && item->existsInLeft()) { if (item->task() == TT_COPY_TO_LEFT) item->setTask(TT_COPY_TO_RIGHT); else if (item->task() == TT_COPY_TO_RIGHT) item->setTask(TT_COPY_TO_LEFT); } } void Synchronizer::reverseDirection(SynchronizerFileItem *item) { operate(item, reverseDirectionOperation); } void Synchronizer::deleteLeftOperation(SynchronizerFileItem *item) { if (!item->existsInRight() && item->existsInLeft()) item->setTask(TT_DELETE); } void Synchronizer::deleteLeft(SynchronizerFileItem *item) { operate(item, deleteLeftOperation); } void Synchronizer::copyToLeftOperation(SynchronizerFileItem *item) { if (item->existsInRight()) { if (!item->isDir()) item->setTask(TT_COPY_TO_LEFT); else { if (item->existsInLeft() && item->existsInRight()) item->setTask(TT_EQUALS); else if (!item->existsInLeft() && item->existsInRight()) item->setTask(TT_COPY_TO_LEFT); } } } void Synchronizer::copyToLeft(SynchronizerFileItem *item) { operate(item, copyToLeftOperation); while ((item = item->parent()) != 0) { if (item->task() != TT_DIFFERS) break; if (item->existsInLeft() && item->existsInRight()) item->setTask(TT_EQUALS); else if (!item->existsInLeft() && item->existsInRight()) item->setTask(TT_COPY_TO_LEFT); } } void Synchronizer::copyToRightOperation(SynchronizerFileItem *item) { if (item->existsInLeft()) { if (!item->isDir()) item->setTask(TT_COPY_TO_RIGHT); else { if (item->existsInLeft() && item->existsInRight()) item->setTask(TT_EQUALS); else if (item->existsInLeft() && !item->existsInRight()) item->setTask(TT_COPY_TO_RIGHT); } } } void Synchronizer::copyToRight(SynchronizerFileItem *item) { operate(item, copyToRightOperation); while ((item = item->parent()) != 0) { if (item->task() != TT_DIFFERS && item->task() != TT_DELETE) break; if (item->existsInLeft() && item->existsInRight()) item->setTask(TT_EQUALS); else if (item->existsInLeft() && !item->existsInRight()) item->setTask(TT_COPY_TO_RIGHT); } } bool Synchronizer::totalSizes(int * leftCopyNr, KIO::filesize_t *leftCopySize, int * rightCopyNr, KIO::filesize_t *rightCopySize, int *deleteNr, KIO::filesize_t *deletableSize) { bool hasAnythingToDo = false; *leftCopySize = *rightCopySize = *deletableSize = 0; *leftCopyNr = *rightCopyNr = *deleteNr = 0; QListIterator it(resultList); while (it.hasNext()) { SynchronizerFileItem * item = it.next(); if (item->isMarked()) { switch (item->task()) { case TT_COPY_TO_LEFT: *leftCopySize += item->rightSize(); (*leftCopyNr)++; hasAnythingToDo = true; break; case TT_COPY_TO_RIGHT: *rightCopySize += item->leftSize(); (*rightCopyNr)++; hasAnythingToDo = true; break; case TT_DELETE: *deletableSize += item->leftSize(); (*deleteNr)++; hasAnythingToDo = true; break; default: break; } } } return hasAnythingToDo; } void Synchronizer::swapSides() { QString leftTmp = leftBaseDir; leftBaseDir = rightBaseDir; rightBaseDir = leftTmp; QListIterator it(resultList); while (it.hasNext()) { SynchronizerFileItem * item = it.next(); item->swap(asymmetric); } } void Synchronizer::setScrolling(bool scroll) { autoScroll = scroll; if (autoScroll) { int oldFileCount = fileCount; refresh(true); fileCount = oldFileCount; } } void Synchronizer::synchronize(QWidget *syncWdg, bool leftCopyEnabled, bool rightCopyEnabled, bool deleteEnabled, bool overWrite, int parThreads) { this->leftCopyEnabled = leftCopyEnabled; this->rightCopyEnabled = rightCopyEnabled; this->deleteEnabled = deleteEnabled; this->overWrite = overWrite; this->parallelThreads = parThreads; this->syncDlgWidget = syncWdg; autoSkip = paused = disableNewTasks = false; leftCopyNr = rightCopyNr = deleteNr = 0; leftCopySize = rightCopySize = deleteSize = 0; inTaskFinished = 0; lastTask = 0; jobMap.clear(); receivedMap.clear(); resultListIt = resultList; synchronizeLoop(); } void Synchronizer::synchronizeLoop() { if (disableNewTasks) { if (!resultListIt.hasNext() && jobMap.count() == 0) emit synchronizationFinished(); return; } while ((int)jobMap.count() < parallelThreads) { SynchronizerFileItem *task = getNextTask(); if (task == 0) { if (jobMap.count() == 0) emit synchronizationFinished(); return; } executeTask(task); if (disableNewTasks) break; } } SynchronizerFileItem * Synchronizer::getNextTask() { TaskType task; SynchronizerFileItem * currentTask; do { if (!resultListIt.hasNext()) return 0; currentTask = resultListIt.next(); if (currentTask->isMarked()) { task = currentTask->task(); if (leftCopyEnabled && task == TT_COPY_TO_LEFT) break; else if (rightCopyEnabled && task == TT_COPY_TO_RIGHT) break; else if (deleteEnabled && task == TT_DELETE) break; } } while (true); return lastTask = currentTask; } void Synchronizer::executeTask(SynchronizerFileItem * task) { QString leftDirName = task->leftDirectory(); if (!leftDirName.isEmpty()) leftDirName += '/'; QString rightDirName = task->rightDirectory(); if (!rightDirName.isEmpty()) rightDirName += '/'; QUrl leftURL = Synchronizer::fsUrl(leftBaseDir + leftDirName + task->leftName()); QUrl rightURL = Synchronizer::fsUrl(rightBaseDir + rightDirName + task->rightName()); switch (task->task()) { case TT_COPY_TO_LEFT: if (task->isDir()) { KIO::SimpleJob *job = KIO::mkdir(leftURL); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); jobMap[ job ] = task; disableNewTasks = true; } else { QUrl destURL(leftURL); if (!task->destination().isNull()) destURL = Synchronizer::fsUrl(task->destination()); if (task->rightLink().isNull()) { KIO::FileCopyJob *job = KIO::file_copy(rightURL, destURL, -1, ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); connect(job, SIGNAL(processedSize(KJob*,qulonglong)), this, SLOT(slotProcessedSize(KJob*,qulonglong))); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); jobMap[ job ] = task; } else { KIO::SimpleJob *job = KIO::symlink(task->rightLink(), destURL, ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); jobMap[ job ] = task; } } break; case TT_COPY_TO_RIGHT: if (task->isDir()) { KIO::SimpleJob *job = KIO::mkdir(rightURL); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); jobMap[ job ] = task; disableNewTasks = true; } else { QUrl destURL(rightURL); if (!task->destination().isNull()) destURL = Synchronizer::fsUrl(task->destination()); if (task->leftLink().isNull()) { KIO::FileCopyJob *job = KIO::file_copy(leftURL, destURL, -1, ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); connect(job, SIGNAL(processedSize(KJob*,qulonglong)), this, SLOT(slotProcessedSize(KJob*,qulonglong))); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); jobMap[ job ] = task; } else { KIO::SimpleJob *job = KIO::symlink(task->leftLink(), destURL, ((overWrite || task->overWrite()) ? KIO::Overwrite : KIO::DefaultFlags) | KIO::HideProgressInfo); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); jobMap[ job ] = task; } } break; case TT_DELETE: { KIO::DeleteJob *job = KIO::del(leftURL, KIO::DefaultFlags); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotTaskFinished(KJob*))); jobMap[ job ] = task; } break; default: break; } } void Synchronizer::slotTaskFinished(KJob *job) { inTaskFinished++; SynchronizerFileItem * item = jobMap[ job ]; jobMap.remove(job); KIO::filesize_t receivedSize = 0; if (receivedMap.contains(job)) { receivedSize = receivedMap[ job ]; receivedMap.remove(job); } if (disableNewTasks && item == lastTask) disableNewTasks = false; // the blocker task finished QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; QUrl leftURL = Synchronizer::fsUrl(leftBaseDir + leftDirName + item->leftName()); QUrl rightURL = Synchronizer::fsUrl(rightBaseDir + rightDirName + item->rightName()); do { if (!job->error()) { switch (item->task()) { case TT_COPY_TO_LEFT: if (leftURL.isLocalFile()) { struct utimbuf timestamp; timestamp.actime = time(0); timestamp.modtime = item->rightDate() - timeOffset; utime((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), ×tamp); uid_t newOwnerID = (uid_t) - 1; // chown(2) : -1 means no change if (!item->rightOwner().isEmpty()) { struct passwd* pw = getpwnam(QFile::encodeName(item->rightOwner())); if (pw != 0L) newOwnerID = pw->pw_uid; } gid_t newGroupID = (gid_t) - 1; // chown(2) : -1 means no change if (!item->rightGroup().isEmpty()) { struct group* g = getgrnam(QFile::encodeName(item->rightGroup())); if (g != 0L) newGroupID = g->gr_gid; } int status1 = chown((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), newOwnerID, (gid_t) - 1); int status2 = chown((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), (uid_t) - 1, newGroupID); if (status1 < 0 || status2 < 0) { // synchronizer currently ignores chown errors } chmod((const char *)(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), item->rightMode() & 07777); #ifdef HAVE_POSIX_ACL if (!item->rightACL().isNull()) { acl_t acl = acl_from_text(item->rightACL().toLatin1()); if (acl && !acl_valid(acl)) acl_set_file(leftURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit(), ACL_TYPE_ACCESS, acl); if (acl) acl_free(acl); } #endif } break; case TT_COPY_TO_RIGHT: if (rightURL.isLocalFile()) { struct utimbuf timestamp; timestamp.actime = time(0); timestamp.modtime = item->leftDate() + timeOffset; utime((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), ×tamp); uid_t newOwnerID = (uid_t) - 1; // chown(2) : -1 means no change if (!item->leftOwner().isEmpty()) { struct passwd* pw = getpwnam(QFile::encodeName(item->leftOwner())); if (pw != 0L) newOwnerID = pw->pw_uid; } gid_t newGroupID = (gid_t) - 1; // chown(2) : -1 means no change if (!item->leftGroup().isEmpty()) { struct group* g = getgrnam(QFile::encodeName(item->leftGroup())); if (g != 0L) newGroupID = g->gr_gid; } int status1 = chown((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), newOwnerID, (uid_t) - 1); int status2 = chown((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), (uid_t) - 1, newGroupID); if (status1 < 0 || status2 < 0) { // synchronizer currently ignores chown errors } chmod((const char *)(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit()), item->leftMode() & 07777); #ifdef HAVE_POSIX_ACL if (!item->leftACL().isNull()) { acl_t acl = acl_from_text(item->leftACL().toLatin1()); if (acl && !acl_valid(acl)) acl_set_file(rightURL.adjusted(QUrl::StripTrailingSlash).path().toLocal8Bit(), ACL_TYPE_ACCESS, acl); if (acl) acl_free(acl); } #endif } break; default: break; } } else { if (job->error() == KIO::ERR_FILE_ALREADY_EXIST && item->task() != TT_DELETE) { KIO::RenameDialog_Result result; QString newDest; if (autoSkip) break; KIO::JobUiDelegate *ui = static_cast(job->uiDelegate()); ui->setWindow(syncDlgWidget); if (item->task() == TT_COPY_TO_LEFT) { result = ui->askFileRename(job, i18n("File Already Exists"), rightURL, leftURL, KIO::RenameDialog_Overwrite | KIO::RenameDialog_Skip | KIO::RenameDialog_MultipleItems, newDest, item->rightSize(), item->leftSize(), QDateTime(), QDateTime(), QDateTime::fromTime_t(item->rightDate()), QDateTime::fromTime_t(item->leftDate())); } else { result = ui->askFileRename(job, i18n("File Already Exists"), leftURL, rightURL, KIO::RenameDialog_Overwrite | KIO::RenameDialog_Skip | KIO::RenameDialog_MultipleItems, newDest, item->leftSize(), item->rightSize(), QDateTime(), QDateTime(), QDateTime::fromTime_t(item->leftDate()), QDateTime::fromTime_t(item->rightDate())); } switch (result) { case KIO::R_RENAME: item->setDestination(newDest); executeTask(item); inTaskFinished--; return; case KIO::R_OVERWRITE: item->setOverWrite(); executeTask(item); inTaskFinished--; return; case KIO::R_OVERWRITE_ALL: overWrite = true; executeTask(item); inTaskFinished--; return; case KIO::R_AUTO_SKIP: autoSkip = true; case KIO::R_SKIP: default: break; } break; } if (job->error() != KIO::ERR_DOES_NOT_EXIST || item->task() != TT_DELETE) { if (autoSkip) break; QString error; switch (item->task()) { case TT_COPY_TO_LEFT: error = i18n("Error at copying file %1 to %2.", rightURL.toDisplayString(QUrl::PreferLocalFile), leftURL.toDisplayString(QUrl::PreferLocalFile)); break; case TT_COPY_TO_RIGHT: error = i18n("Error at copying file %1 to %2.", leftURL.toDisplayString(QUrl::PreferLocalFile), rightURL.toDisplayString(QUrl::PreferLocalFile)); break; case TT_DELETE: error = i18n("Error at deleting file %1.", leftURL.toDisplayString(QUrl::PreferLocalFile)); break; default: break; } KIO::JobUiDelegate *ui = static_cast(job->uiDelegate()); ui->setWindow(syncDlgWidget); KIO::SkipDialog_Result result = ui->askSkip(job, KIO::SkipDialog_MultipleItems, error); switch (result) { case KIO::S_CANCEL: executeTask(item); /* simply retry */ inTaskFinished--; return; case KIO::S_AUTO_SKIP: autoSkip = true; default: break; } } } } while (false); switch (item->task()) { case TT_COPY_TO_LEFT: leftCopyNr++; leftCopySize += item->rightSize() - receivedSize; break; case TT_COPY_TO_RIGHT: rightCopyNr++; rightCopySize += item->leftSize() - receivedSize; break; case TT_DELETE: deleteNr++; deleteSize += item->leftSize() - receivedSize; break; default: break; } emit processedSizes(leftCopyNr, leftCopySize, rightCopyNr, rightCopySize, deleteNr, deleteSize); if (--inTaskFinished == 0) { if (paused) emit pauseAccepted(); else synchronizeLoop(); } } void Synchronizer::slotProcessedSize(KJob * job , qulonglong size) { KIO::filesize_t dl = 0, dr = 0, dd = 0; SynchronizerFileItem * item = jobMap[ job ]; KIO::filesize_t lastProcessedSize = 0; if (receivedMap.contains(job)) lastProcessedSize = receivedMap[ job ]; receivedMap[ job ] = size; switch (item->task()) { case TT_COPY_TO_LEFT: dl = size - lastProcessedSize; break; case TT_COPY_TO_RIGHT: dr = size - lastProcessedSize; break; case TT_DELETE: dd = size - lastProcessedSize; break; default: break; } emit processedSizes(leftCopyNr, leftCopySize += dl, rightCopyNr, rightCopySize += dr, deleteNr, deleteSize += dd); } void Synchronizer::pause() { paused = true; } void Synchronizer::resume() { paused = false; synchronizeLoop(); } QString Synchronizer::leftBaseDirectory() { return leftBaseDir; } QString Synchronizer::rightBaseDirectory() { return rightBaseDir; } KgetProgressDialog::KgetProgressDialog(QWidget *parent, const QString &caption, const QString &text, bool modal) : QDialog(parent) { if (caption.isEmpty()) setWindowTitle(caption); setModal(modal); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); mainLayout->addWidget(new QLabel(text)); mProgressBar = new QProgressBar; mainLayout->addWidget(mProgressBar); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel); mainLayout->addWidget(buttonBox); mPauseButton = new QPushButton(i18n("Pause")); buttonBox->addButton(mPauseButton, QDialogButtonBox::ActionRole); buttonBox->button(QDialogButtonBox::Cancel)->setDefault(true); connect(mPauseButton, SIGNAL(clicked()), SLOT(slotPause())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(slotCancel())); mCancelled = mPaused = false; } void KgetProgressDialog::slotPause() { if ((mPaused = !mPaused) == false) mPauseButton->setText(i18n("Pause")); else mPauseButton->setText(i18n("Resume")); } void KgetProgressDialog::slotCancel() { mCancelled = true; reject(); } void Synchronizer::synchronizeWithKGet() { bool isLeftLocal = QUrl::fromUserInput(leftBaseDirectory(), QString(), QUrl::AssumeLocalFile).isLocalFile(); KgetProgressDialog *progDlg = 0; int processedCount = 0, totalCount = 0; QListIterator it(resultList); while (it.hasNext()) if (it.next()->isMarked()) totalCount++; it.toFront(); while (it.hasNext()) { SynchronizerFileItem * item = it.next(); if (item->isMarked()) { QUrl downloadURL; QUrl destURL; QString destDir; QString leftDirName = item->leftDirectory().isEmpty() ? "" : item->leftDirectory() + '/'; QString rightDirName = item->rightDirectory().isEmpty() ? "" : item->rightDirectory() + '/'; if (progDlg == 0) { progDlg = new KgetProgressDialog(krMainWindow, i18n("Krusader::Synchronizer"), i18n("Feeding the URLs to KGet"), true); progDlg->progressBar()->setMaximum(totalCount); progDlg->show(); qApp->processEvents(); } if (item->task() == TT_COPY_TO_RIGHT && !isLeftLocal) { downloadURL = Synchronizer::fsUrl(leftBaseDirectory() + leftDirName + item->leftName()); destDir = rightBaseDirectory() + rightDirName; destURL = Synchronizer::fsUrl(destDir + item->rightName()); if (item->isDir()) destDir += item->leftName(); } if (item->task() == TT_COPY_TO_LEFT && isLeftLocal) { downloadURL = Synchronizer::fsUrl(rightBaseDirectory() + rightDirName + item->rightName()); destDir = leftBaseDirectory() + leftDirName; destURL = Synchronizer::fsUrl(destDir + item->leftName()); if (item->isDir()) destDir += item->rightName(); } // creating the directory system for (int i = 0; i >= 0 ; i = destDir.indexOf('/', i + 1)) if (!QDir(destDir.left(i)).exists()) QDir().mkdir(destDir.left(i)); if (!item->isDir() && !downloadURL.isEmpty()) { if (QFile(destURL.path()).exists()) QFile(destURL.path()).remove(); QString source = downloadURL.toDisplayString(); if (source.indexOf('@') >= 2) { /* is this an ftp proxy URL? */ int lastAt = source.lastIndexOf('@'); QString startString = source.left(lastAt); QString endString = source.mid(lastAt); startString.replace('@', "%40"); source = startString + endString; } KProcess p; p << KrServices::fullPathName("kget") << source << destURL.path(); if (!p.startDetached()) KMessageBox::error(parentWidget, i18n("Error executing %1.", KrServices::fullPathName("kget"))); } progDlg->progressBar()->setValue(++processedCount); QTime t; t.start(); bool canExit = false; do { qApp->processEvents(); if (progDlg->wasCancelled()) break; canExit = (t.elapsed() > 100); if (progDlg->isPaused() || !canExit) usleep(10000); } while (progDlg->isPaused() || !canExit); if (progDlg->wasCancelled()) break; } } if (progDlg) delete progDlg; } bool Synchronizer::isDir(const FileItem *file) { if (followSymLinks) { return file->isDir(); } else { return file->isDir() && !file->isSymLink(); } } QString Synchronizer::readLink(const FileItem *file) { if (file->isSymLink()) return file->getSymDest(); else return QString(); } SynchronizerFileItem *Synchronizer::getItemAt(unsigned ndx) { if (ndx < (unsigned)resultList.count()) return resultList.at(ndx); else return 0; } diff --git a/krusader/Synchronizer/synchronizer.h b/krusader/Synchronizer/synchronizer.h index c0518ea2..c0cddfdd 100644 --- a/krusader/Synchronizer/synchronizer.h +++ b/krusader/Synchronizer/synchronizer.h @@ -1,243 +1,233 @@ -/*************************************************************************** - synchronizer.h - description - ------------------- - copyright : (C) 2003 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef SYNCHRONIZER_H #define SYNCHRONIZER_H // QtCore #include #include #include // QtGui #include // QtWidgets #include #include # include "synchronizertask.h" #include "synchronizerfileitem.h" class KRQuery; class FileItem; class Synchronizer : public QObject { Q_OBJECT private: int displayUpdateCount; // the display is refreshed after every x-th change public: Synchronizer(); ~Synchronizer(); int compare(QString leftURL, QString rightURL, KRQuery *query, bool subDirs, bool symLinks, bool igDate, bool asymm, bool cmpByCnt, bool igCase, bool autoSc, QStringList &selFiles, int equThres, int timeOffs, int parThreads, bool hiddenFiles); void stop() { stopped = true; } void setMarkFlags(bool left, bool equal, bool differs, bool right, bool dup, bool sing, bool del); int refresh(bool nostatus = false); bool totalSizes(int *, KIO::filesize_t *, int *, KIO::filesize_t *, int *, KIO::filesize_t *); void synchronize(QWidget *, bool leftCopyEnabled, bool rightCopyEnabled, bool deleteEnabled, bool overWrite, int parThreads); void synchronizeWithKGet(); void setScrolling(bool scroll); void pause(); void resume(); void swapSides(); void reset(); void clearLists(); void exclude(SynchronizerFileItem *); void restore(SynchronizerFileItem *); void reverseDirection(SynchronizerFileItem *); void copyToLeft(SynchronizerFileItem *); void copyToRight(SynchronizerFileItem *); void deleteLeft(SynchronizerFileItem *); QString leftBaseDirectory(); QString rightBaseDirectory(); static QString getTaskTypeName(TaskType taskType); static QUrl fsUrl(QString strUrl); SynchronizerFileItem *getItemAt(unsigned ndx); void setParentWidget(QWidget * widget) { parentWidget = widget; } void compareContentResult(SynchronizerFileItem * item, bool result); signals: void comparedFileData(SynchronizerFileItem *); void markChanged(SynchronizerFileItem *, bool); void synchronizationFinished(); void processedSizes(int, KIO::filesize_t, int, KIO::filesize_t, int, KIO::filesize_t); void pauseAccepted(); void statusInfo(QString); public slots: void slotTaskFinished(KJob*); void slotProcessedSize(KJob * , qulonglong); private: bool isDir(const FileItem * file); QString readLink(const FileItem * file); void compareDirectory(SynchronizerFileItem *, SynchronizerDirList *, SynchronizerDirList *, const QString &leftDir, const QString &rightDir); void addSingleDirectory(SynchronizerFileItem *, SynchronizerDirList *, const QString &, bool); SynchronizerFileItem * addItem(SynchronizerFileItem *, const QString &, const QString &, const QString &, const QString &, bool, bool, KIO::filesize_t, KIO::filesize_t, time_t, time_t, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, mode_t, mode_t, const QString &, const QString &, TaskType, bool, bool); SynchronizerFileItem * addLeftOnlyItem(SynchronizerFileItem *, const QString &, const QString &, KIO::filesize_t, time_t, const QString &, const QString &, const QString &, mode_t, const QString &, bool isDir = false, bool isTemp = false); SynchronizerFileItem * addRightOnlyItem(SynchronizerFileItem *, const QString &, const QString &, KIO::filesize_t, time_t, const QString &, const QString &, const QString &, mode_t, const QString &, bool isDir = false, bool isTemp = false); SynchronizerFileItem * addDuplicateItem(SynchronizerFileItem *, const QString &, const QString &, const QString &, const QString &, KIO::filesize_t, KIO::filesize_t, time_t, time_t, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, mode_t, mode_t, const QString &, const QString &, bool isDir = false, bool isTemp = false); bool isMarked(TaskType task, bool dupl); bool markParentDirectories(SynchronizerFileItem *); void synchronizeLoop(); SynchronizerFileItem * getNextTask(); void executeTask(SynchronizerFileItem * task); void setPermanent(SynchronizerFileItem *); void operate(SynchronizerFileItem *item, void (*)(SynchronizerFileItem *)); void compareLoop(); static void excludeOperation(SynchronizerFileItem *item); static void restoreOperation(SynchronizerFileItem *item); static void reverseDirectionOperation(SynchronizerFileItem *item); static void copyToLeftOperation(SynchronizerFileItem *item); static void copyToRightOperation(SynchronizerFileItem *item); static void deleteLeftOperation(SynchronizerFileItem *item); protected: bool recurseSubDirs; // walk through subdirectories also bool followSymLinks; // follow the symbolic links bool ignoreDate; // don't use date info at comparing bool asymmetric; // asymmetric directory update bool cmpByContent; // compare the files by content bool ignoreCase; // case insensitive synchronization for Windows fs bool autoScroll; // automatic update of the directory QList resultList; // the found files QList temporaryList; // temporary files QString leftBaseDir; // the left-side base directory QString rightBaseDir; // the right-side base directory QStringList excludedPaths; // list of the excluded paths KRQuery *query; // the filter used for the query bool stopped; // 'Stop' button was pressed int equalsThreshold;// threshold to treat files equal int timeOffset; // time offset between the left and right sides bool ignoreHidden; // ignores the hidden files bool markEquals; // show the equal files bool markDiffers; // show the different files bool markCopyToLeft; // show the files to copy from right to left bool markCopyToRight;// show the files to copy from left to right bool markDeletable; // show the files to be deleted bool markDuplicates; // show the duplicated items bool markSingles; // show the single items bool leftCopyEnabled;// copy to left is enabled at synchronize bool rightCopyEnabled;// copy to right is enabled at synchronize bool deleteEnabled; // delete is enabled at synchronize bool overWrite; // overwrite or query each modification bool autoSkip; // automatic skipping bool paused; // pause flag bool disableNewTasks;// at mkdir the further task creation is disabled int leftCopyNr; // the file number copied to left int rightCopyNr; // the file number copied to right int deleteNr; // the number of the deleted files int parallelThreads;// the number of the parallel procesing threads KIO::filesize_t leftCopySize; // the total size copied to left KIO::filesize_t rightCopySize; // the total size copied to right KIO::filesize_t deleteSize; // the size of the deleted files int comparedDirs; // the number of the compared directories int fileCount; // the number of counted files private: QList stack; // stack for comparing QMap jobMap; // job maps QMap receivedMap; // the received file size SynchronizerFileItem *lastTask; // reference to the last stack int inTaskFinished; // counter of quasy 'threads' in slotTaskFinished QStringList selectedFiles; // the selected files to compare QWidget *parentWidget; // the parent widget QWidget *syncDlgWidget; // the synchronizer dialog widget QListIterator resultListIt; // iterator for result list }; class QProgressBar; class KgetProgressDialog : public QDialog { Q_OBJECT public: explicit KgetProgressDialog(QWidget *parent = 0, const QString &caption = QString(), const QString &text = QString(), bool modal = false); QProgressBar *progressBar() { return mProgressBar; } public slots: void slotPause(); void slotCancel(); bool wasCancelled() { return mCancelled; } bool isPaused() { return mPaused; } private: QProgressBar *mProgressBar; QPushButton *mPauseButton; bool mCancelled; bool mPaused; }; #endif /* __SYNCHRONIZER_H__ */ diff --git a/krusader/Synchronizer/synchronizercolors.h b/krusader/Synchronizer/synchronizercolors.h index c1c967f9..a7bbc33d 100644 --- a/krusader/Synchronizer/synchronizercolors.h +++ b/krusader/Synchronizer/synchronizercolors.h @@ -1,51 +1,41 @@ -/*************************************************************************** - synchronizercolors.h - description - ------------------- - copyright : (C) 2016 + by Krusader Krew - web site : http://www.krusader.org/ - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2016-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef SYNCHRONIZERCOLORS_H #define SYNCHRONIZERCOLORS_H #include #define DECLARE_SYNCHRONIZER_BACKGROUND_DEFAULTS QColor SYNCHRONIZER_BACKGROUND_DEFAULTS[] = { \ QGuiApplication::palette().color(QPalette::Active, QPalette::Base), \ QGuiApplication::palette().color(QPalette::Active, QPalette::Base), \ QGuiApplication::palette().color(QPalette::Active, QPalette::Base), \ QGuiApplication::palette().color(QPalette::Active, QPalette::Base), \ KColorUtils::tint(QGuiApplication::palette().color(QPalette::Active, QPalette::Base), Qt::red, 0.5) \ } #define DECLARE_SYNCHRONIZER_FOREGROUND_DEFAULTS QColor SYNCHRONIZER_FOREGROUND_DEFAULTS[] = { \ QGuiApplication::palette().color(QPalette::Active, QPalette::Text), \ KColorUtils::tint(QGuiApplication::palette().color(QPalette::Active, QPalette::Text), Qt::red, 0.7), \ KColorUtils::tint(QGuiApplication::palette().color(QPalette::Active, QPalette::Text), QColor(0, 115, 207), 0.7), \ KColorUtils::tint(QGuiApplication::palette().color(QPalette::Active, QPalette::Text), Qt::green, 0.5), \ QGuiApplication::palette().color(QPalette::Active, QPalette::Text) \ } #endif /* __SYNCHRONIZERCOLORS_H__ */ diff --git a/krusader/Synchronizer/synchronizerdirlist.cpp b/krusader/Synchronizer/synchronizerdirlist.cpp index 4caa45bb..fbf5baf0 100644 --- a/krusader/Synchronizer/synchronizerdirlist.cpp +++ b/krusader/Synchronizer/synchronizerdirlist.cpp @@ -1,193 +1,183 @@ -/*************************************************************************** - synchronizerdirlist.cpp - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "synchronizerdirlist.h" #ifdef HAVE_POSIX_ACL #include #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS #include #endif #endif #include // QtCore #include // QtWidgets #include #include #include #include #include #include "../FileSystem/filesystem.h" #include "../FileSystem/krpermhandler.h" #include "../krservices.h" SynchronizerDirList::SynchronizerDirList(QWidget *w, bool hidden) : QObject(), QHash(), fileIterator(0), parentWidget(w), busy(false), result(false), ignoreHidden(hidden), currentUrl() { } SynchronizerDirList::~SynchronizerDirList() { if (fileIterator) delete fileIterator; QHashIterator< QString, FileItem *> lit(*this); while (lit.hasNext()) delete lit.next().value(); } FileItem *SynchronizerDirList::search(const QString &name, bool ignoreCase) { if (!ignoreCase) { if (!contains(name)) return 0; return (*this)[ name ]; } QHashIterator iter(*this); iter.toFront(); QString file = name.toLower(); while (iter.hasNext()) { FileItem *item = iter.next().value(); if (file == item->getName().toLower()) return item; } return 0; } FileItem *SynchronizerDirList::first() { if (fileIterator == 0) fileIterator = new QHashIterator (*this); fileIterator->toFront(); if (fileIterator->hasNext()) return fileIterator->next().value(); return 0; } FileItem *SynchronizerDirList::next() { if (fileIterator == 0) fileIterator = new QHashIterator (*this); if (fileIterator->hasNext()) return fileIterator->next().value(); return 0; } bool SynchronizerDirList::load(const QString &urlIn, bool wait) { if (busy) return false; currentUrl = urlIn; const QUrl url = QUrl::fromUserInput(urlIn, QString(), QUrl::AssumeLocalFile); QHashIterator< QString, FileItem *> lit(*this); while (lit.hasNext()) delete lit.next().value(); clear(); if (fileIterator) { delete fileIterator; fileIterator = 0; } if (url.isLocalFile()) { const QString dir = FileSystem::ensureTrailingSlash(url).path(); QT_DIR* qdir = QT_OPENDIR(dir.toLocal8Bit()); if (!qdir) { KMessageBox::error(parentWidget, i18n("Cannot open the folder %1.", dir), i18n("Error")); emit finished(result = false); return false; } QT_DIRENT* dirEnt; while ((dirEnt = QT_READDIR(qdir)) != NULL) { const QString name = QString::fromLocal8Bit(dirEnt->d_name); if (name == "." || name == "..") continue; if (ignoreHidden && name.startsWith('.')) continue; FileItem *item = FileSystem::createLocalFileItem(name, dir); insert(name, item); } QT_CLOSEDIR(qdir); emit finished(result = true); return true; } else { KIO::Job *job = KIO::listDir(KrServices::escapeFileUrl(url), KIO::HideProgressInfo, true); connect(job, SIGNAL(entries(KIO::Job*,KIO::UDSEntryList)), this, SLOT(slotEntries(KIO::Job*,KIO::UDSEntryList))); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotListResult(KJob*))); busy = true; if (!wait) return true; while (busy) qApp->processEvents(); return result; } } void SynchronizerDirList::slotEntries(KIO::Job *job, const KIO::UDSEntryList& entries) { KIO::ListJob *listJob = static_cast(job); for (const KIO::UDSEntry entry : entries) { FileItem *item = FileSystem::createFileItemFromKIO(entry, listJob->url()); if (item) { insert(item->getName(), item); } } } void SynchronizerDirList::slotListResult(KJob *job) { busy = false; if (job && job->error()) { job->uiDelegate()->showErrorMessage(); emit finished(result = false); return; } emit finished(result = true); } diff --git a/krusader/Synchronizer/synchronizerdirlist.h b/krusader/Synchronizer/synchronizerdirlist.h index bb32a113..01e4ab08 100644 --- a/krusader/Synchronizer/synchronizerdirlist.h +++ b/krusader/Synchronizer/synchronizerdirlist.h @@ -1,76 +1,66 @@ -/*************************************************************************** - synchronizerdirlist.h - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef SYNCHRONIZERDIRLIST_H #define SYNCHRONIZERDIRLIST_H // QtCore #include #include #include #include "../FileSystem/fileitem.h" class SynchronizerDirList : public QObject, public QHash { Q_OBJECT public: SynchronizerDirList(QWidget *w, bool ignoreHidden); ~SynchronizerDirList(); FileItem *search(const QString &name, bool ignoreCase = false); FileItem *first(); FileItem *next(); inline const QString & url() { return currentUrl; } bool load(const QString &urlIn, bool wait = false); public slots: void slotEntries(KIO::Job * job, const KIO::UDSEntryList& entries); void slotListResult(KJob *job); signals: void finished(bool err); private: QHashIterator *fileIterator; //< Point to a dictionary of file items QWidget *parentWidget; bool busy; bool result; bool ignoreHidden; QString currentUrl; }; #endif /* __SYNCHRONIZER_DIR_LIST_H__ */ diff --git a/krusader/Synchronizer/synchronizerfileitem.h b/krusader/Synchronizer/synchronizerfileitem.h index 18157bf3..ae2ca036 100644 --- a/krusader/Synchronizer/synchronizerfileitem.h +++ b/krusader/Synchronizer/synchronizerfileitem.h @@ -1,245 +1,235 @@ -/*************************************************************************** - synchronizerfileitem.h - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef SYNCHRONIZERFILEITEM_H #define SYNCHRONIZERFILEITEM_H // QtCore #include #include typedef enum { TT_EQUALS = 0, // the files are equals -> do nothing TT_DIFFERS = 1, // the files are differents -> don't know what to do TT_COPY_TO_LEFT = 2, // the right file is newer -> copy from right to left TT_COPY_TO_RIGHT = 3, // the left file is newer -> copy from left to right TT_DELETE = 4, // the left file is single -> delete it TT_UNKNOWN = 5, // (5-9) the type of the task is not yet known TT_MAX = 10 // the maximum number of task types } TaskType; #define SWAP( A, B, TYPE ) {TYPE TMP = A; A = B; B = TMP;} #define REVERSE_TASK( A, asym ) {switch( A ) \ { \ case TT_COPY_TO_LEFT: \ if( asym ) \ A = !m_existsRight ? TT_DELETE : TT_COPY_TO_LEFT; \ else \ A = TT_COPY_TO_RIGHT; \ break; \ case TT_COPY_TO_RIGHT: \ case TT_DELETE: \ A = TT_COPY_TO_LEFT; \ default: \ break; \ }}; class SynchronizerFileItem { private: QString m_leftName; // the left file name QString m_rightName; // the right file name QString m_leftDirectory;// the left relative directory path from the base QString m_rightDirectory;// the left relative directory path from the base bool m_marked; // flag, indicates to show the file bool m_existsLeft; // flag, the file exists in the left directory bool m_existsRight; // flag, the file exists in the right directory KIO::filesize_t m_leftSize; // the file size at the left directory KIO::filesize_t m_rightSize; // the file size at the right directory time_t m_leftDate; // the file date at the left directory time_t m_rightDate; // the file date at the left directory QString m_leftLink; // the left file's symbolic link destination QString m_rightLink; // the right file's symbolic link destination QString m_leftOwner; // the left file's owner QString m_rightOwner; // the right file's owner QString m_leftGroup; // the left file's group QString m_rightGroup; // the right file's group mode_t m_leftMode; // mode for left mode_t m_rightMode; // mode for right QString m_leftACL; // ACL of the left file QString m_rightACL; // ACL of the right file TaskType m_task; // the task with the file bool m_isDir; // flag, indicates that the file is a directory SynchronizerFileItem *m_parent; // pointer to the parent directory item or 0 void *m_userData; // user data bool m_overWrite; // overwrite flag QString m_destination; // the destination URL at rename bool m_temporary; // flag indicates temporary directory TaskType m_originalTask; // the original task type public: SynchronizerFileItem(const QString &leftNam, const QString &rightNam, const QString &leftDir, const QString &rightDir, bool mark, bool exL, bool exR, KIO::filesize_t leftSize, KIO::filesize_t rightSize, time_t leftDate, time_t rightDate, const QString &leftLink, const QString &rightLink, const QString &leftOwner, const QString &rightOwner, const QString &leftGroup, const QString &rightGroup, mode_t leftMode, mode_t rightMode, const QString &leftACL, const QString &rightACL, TaskType tsk, bool isDir, bool tmp, SynchronizerFileItem *parent) : m_leftName(leftNam), m_rightName(rightNam), m_leftDirectory(leftDir), m_rightDirectory(rightDir), m_marked(mark), m_existsLeft(exL), m_existsRight(exR), m_leftSize(leftSize), m_rightSize(rightSize), m_leftDate(leftDate), m_rightDate(rightDate), m_leftLink(leftLink), m_rightLink(rightLink), m_leftOwner(leftOwner), m_rightOwner(rightOwner), m_leftGroup(leftGroup), m_rightGroup(rightGroup), m_leftMode(leftMode), m_rightMode(rightMode), m_leftACL(leftACL), m_rightACL(rightACL), m_task(tsk), m_isDir(isDir), m_parent(parent), m_userData(0), m_overWrite(false), m_destination(QString()), m_temporary(tmp), m_originalTask(tsk) {} inline bool isMarked() { return m_marked; } inline void setMarked(bool flag) { m_marked = flag; } inline const QString & leftName() { return m_leftName; } inline const QString & rightName() { return m_rightName; } inline const QString & leftDirectory() { return m_leftDirectory; } inline const QString & rightDirectory() { return m_rightDirectory; } inline bool existsInLeft() { return m_existsLeft; } inline bool existsInRight() { return m_existsRight; } inline bool overWrite() { return m_overWrite; } inline KIO::filesize_t leftSize() { return m_leftSize; } inline KIO::filesize_t rightSize() { return m_rightSize; } inline time_t leftDate() { return m_leftDate; } inline time_t rightDate() { return m_rightDate; } inline const QString & leftLink() { return m_leftLink; } inline const QString & rightLink() { return m_rightLink; } inline const QString & leftOwner() { return m_leftOwner; } inline const QString & rightOwner() { return m_rightOwner; } inline const QString & leftGroup() { return m_leftGroup; } inline const QString & rightGroup() { return m_rightGroup; } inline mode_t leftMode() { return m_leftMode; } inline mode_t rightMode() { return m_rightMode; } inline const QString & leftACL() { return m_leftACL; } inline const QString & rightACL() { return m_rightACL; } inline TaskType task() { return m_task; } inline void compareContentResult(bool res) { if (res == true) m_task = m_originalTask = TT_EQUALS; else if (m_originalTask >= TT_UNKNOWN) m_task = m_originalTask = (TaskType)(m_originalTask - TT_UNKNOWN); } inline bool isDir() { return m_isDir; } inline SynchronizerFileItem * parent() { return m_parent; } inline void * userData() { return m_userData; } inline void setUserData(void *ud) { m_userData = ud; } inline void setOverWrite() { m_overWrite = true; } inline const QString & destination() { return m_destination; } inline void setDestination(QString d) { m_destination = d; } inline bool isTemporary() { return m_temporary; } inline void setPermanent() { m_temporary = false; } inline TaskType originalTask() { return m_originalTask; } inline void restoreOriginalTask() { m_task = m_originalTask; } inline void setTask(TaskType t) { m_task = t; } inline void swap(bool asym = false) { SWAP(m_existsLeft, m_existsRight, bool); SWAP(m_leftName, m_rightName, QString); SWAP(m_leftDirectory, m_rightDirectory, QString); SWAP(m_leftSize, m_rightSize, KIO::filesize_t); SWAP(m_leftDate, m_rightDate, time_t); SWAP(m_leftLink, m_rightLink, QString); SWAP(m_leftOwner, m_rightOwner, QString); SWAP(m_leftGroup, m_rightGroup, QString); SWAP(m_leftACL, m_rightACL, QString); REVERSE_TASK(m_originalTask, asym); REVERSE_TASK(m_task, asym); } }; #endif /* __SYNCHRONIZER_FILE_ITEM_H__ */ diff --git a/krusader/Synchronizer/synchronizergui.cpp b/krusader/Synchronizer/synchronizergui.cpp index e918523a..a79b2183 100644 --- a/krusader/Synchronizer/synchronizergui.cpp +++ b/krusader/Synchronizer/synchronizergui.cpp @@ -1,1634 +1,1624 @@ -/*************************************************************************** - synchronizergui.cpp - description - ------------------- - copyright : (C) 2003 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "synchronizergui.h" #include "../krglobal.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 "../kicons.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 class SynchronizerListView : public KrTreeWidget { private: Synchronizer *synchronizer; bool isLeft; public: SynchronizerListView(Synchronizer * sync, QWidget * parent) : KrTreeWidget(parent), synchronizer(sync) { } void mouseMoveEvent(QMouseEvent * e) { isLeft = ((e->modifiers() & Qt::ShiftModifier) == 0); KrTreeWidget::mouseMoveEvent(e); } void startDrag(Qt::DropActions /* supportedActs */) { QList urls; unsigned ndx = 0; SynchronizerFileItem *currentItem; while ((currentItem = synchronizer->getItemAt(ndx++)) != 0) { SynchronizerGUI::SyncViewItem *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; QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setImageData(FL_LOADICON(isLeft ? "arrow-left-double" : "arrow-right-double")); mimeData->setUrls(urls); drag->setMimeData(mimeData); drag->start(); } }; SynchronizerGUI::SynchronizerGUI(QWidget* parent, QUrl leftURL, QUrl rightURL, QStringList selList) : QDialog(parent) { initGUI(QString(), leftURL, rightURL, selList); } SynchronizerGUI::SynchronizerGUI(QWidget* parent, QString profile) : QDialog(parent) { initGUI(profile, QUrl(), QUrl(), QStringList()); } void SynchronizerGUI::initGUI(QString profileName, QUrl leftURL, QUrl rightURL, QStringList selList) { setAttribute(Qt::WA_DeleteOnClose); selectedFiles = selList; isComparing = wasClosed = wasSync = false; firstResize = true; sizeX = sizeY = -1; bool equalSizes = 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")); QGridLayout *synchGrid = new QGridLayout(this); synchGrid->setSpacing(6); synchGrid->setContentsMargins(11, 11, 11, 11); synchronizerTabs = new QTabWidget(this); /* ============================== Compare groupbox ============================== */ QWidget *synchronizerTab = new QWidget(this); QGridLayout *synchronizerGrid = new QGridLayout(synchronizerTab); synchronizerGrid->setSpacing(6); synchronizerGrid->setContentsMargins(11, 11, 11, 11); QGroupBox *compareDirs = new QGroupBox(synchronizerTab); compareDirs->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); compareDirs->setTitle(i18n("Folder Comparison")); QGridLayout *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); KUrlRequester *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); KUrlRequester *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); QHBoxLayout *optionBox = new QHBoxLayout(optionWidget); optionBox->setContentsMargins(0, 0, 0, 0); QWidget *optionGridWidget = new QWidget(optionWidget); QGridLayout *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 ============================= */ QGroupBox *showOptions = new QGroupBox(optionWidget); optionBox->addWidget(showOptions); showOptions->setTitle(i18n("S&how options")); showOptions->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); QGridLayout *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"); labels << i18nc("@title:column", "Size"); labels << i18nc("@title:column", "Date"); labels << i18n("<=>"); labels << i18nc("@title:column", "Date"); labels << i18nc("@title:column", "Size"); labels << i18nc("@title:column file name", "Name"); syncList->setHeaderLabels(labels); syncList->header()->setSectionResizeMode(QHeaderView::Interactive); if (group.hasKey("State")) syncList->header()->restoreState(group.readEntry("State", QByteArray())); else { int i = QFontMetrics(syncList->font()).width("W"); int j = QFontMetrics(syncList->font()).width("0"); j = (i > j ? i : j); int typeWidth = j * 7 / 2; syncList->setColumnWidth(0, typeWidth * 4); syncList->setColumnWidth(1, typeWidth * 2); syncList->setColumnWidth(2, typeWidth * 3); syncList->setColumnWidth(3, typeWidth * 1); syncList->setColumnWidth(4, typeWidth * 3); syncList->setColumnWidth(5, typeWidth * 2); syncList->setColumnWidth(6, typeWidth * 4); equalSizes = true; } syncList->setAllColumnsShowFocus(true); syncList->setSelectionMode(QAbstractItemView::ExtendedSelection); syncList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); syncList->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); syncList->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 = (GeneralFilter *)filterTabs->get("GeneralFilter"); generalFilter->searchFor->setEditText(fileFilter->currentText()); generalFilter->searchForCase->setChecked(true); // creating the time shift, equality threshold, hidden files options QGroupBox *optionsGroup = new QGroupBox(generalFilter); optionsGroup->setTitle(i18n("&Options")); QGridLayout *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 =================================== */ QHBoxLayout *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(QIcon::fromTheme("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); QSpacerItem* spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); buttons->addItem(spacer); btnCompareDirs = new QPushButton(this); btnCompareDirs->setText(i18n("Compare")); btnCompareDirs->setIcon(QIcon::fromTheme("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(QIcon::fromTheme("process-stop")); btnStopComparing->setEnabled(false); buttons->addWidget(btnStopComparing); btnFeedToListBox = new QPushButton(this); btnFeedToListBox->setText(i18n("Feed to listbox")); btnFeedToListBox->setIcon(QIcon::fromTheme("list-add")); btnFeedToListBox->setEnabled(false); btnFeedToListBox->hide(); buttons->addWidget(btnFeedToListBox); btnSynchronize = new QPushButton(this); btnSynchronize->setText(i18n("Synchronize")); btnSynchronize->setIcon(QIcon::fromTheme("folder-sync")); btnSynchronize->setEnabled(false); buttons->addWidget(btnSynchronize); QPushButton *btnCloseSync = new QPushButton(this); btnCloseSync->setText(i18n("Close")); btnCloseSync->setIcon(QIcon::fromTheme("dialog-close")); buttons->addWidget(btnCloseSync); synchGrid->addLayout(buttons, 1, 0); /* =============================== Connect table ================================ */ connect(syncList, SIGNAL(itemRightClicked(QTreeWidgetItem*,QPoint,int)), this, SLOT(rightMouseClicked(QTreeWidgetItem*,QPoint))); connect(syncList, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(doubleClicked(QTreeWidgetItem*))); connect(profileManager, SIGNAL(loadFromProfile(QString)), this, SLOT(loadFromProfile(QString))); connect(profileManager, SIGNAL(saveToProfile(QString)), this, SLOT(saveToProfile(QString))); connect(btnSwapSides, SIGNAL(clicked()), this, SLOT(swapSides())); connect(btnCompareDirs, SIGNAL(clicked()), this, SLOT(compare())); connect(btnStopComparing, SIGNAL(clicked()), this, SLOT(stop())); connect(btnFeedToListBox, SIGNAL(clicked()), this, SLOT(feedToListBox())); connect(btnSynchronize, SIGNAL(clicked()), this, SLOT(synchronize())); connect(btnScrollResults, SIGNAL(toggled(bool)), this, SLOT(setScrolling(bool))); connect(btnCloseSync, SIGNAL(clicked()), this, SLOT(closeDialog())); connect(cbSubdirs, SIGNAL(toggled(bool)), this, SLOT(subdirsChecked(bool))); connect(cbAsymmetric, SIGNAL(toggled(bool)), this, SLOT(setPanelLabels())); connect(&synchronizer, SIGNAL(comparedFileData(SynchronizerFileItem*)), this, SLOT(addFile(SynchronizerFileItem*))); connect(&synchronizer, SIGNAL(markChanged(SynchronizerFileItem*,bool)), this, SLOT(markChanged(SynchronizerFileItem*,bool))); connect(&synchronizer, SIGNAL(statusInfo(QString)), this, SLOT(statusInfo(QString))); connect(btnLeftToRight, SIGNAL(toggled(bool)), this, SLOT(refresh())); connect(btnEquals, SIGNAL(toggled(bool)), this, SLOT(refresh())); connect(btnDifferents, SIGNAL(toggled(bool)), this, SLOT(refresh())); connect(btnRightToLeft, SIGNAL(toggled(bool)), this, SLOT(refresh())); connect(btnDeletable, SIGNAL(toggled(bool)), this, SLOT(refresh())); connect(btnDuplicates, SIGNAL(toggled(bool)), this, SLOT(refresh())); connect(btnSingles, SIGNAL(toggled(bool)), this, SLOT(refresh())); connect(fileFilter, SIGNAL(currentTextChanged(QString)), this, SLOT(connectFilters(QString))); connect(generalFilter->searchFor, SIGNAL(currentTextChanged(QString)), this, SLOT(connectFilters(QString))); connect(generalFilter->searchFor, SIGNAL(currentTextChanged(QString)), this, SLOT(setCompletion())); connect(generalFilter->dontSearchIn, SIGNAL(checkValidity(QString&,QString&)), this, SLOT(checkExcludeURLValidity(QString&,QString&))); connect(profileManager, SIGNAL(loadFromProfile(QString)), filterTabs, SLOT(loadFromProfile(QString))); connect(profileManager, SIGNAL(saveToProfile(QString)), filterTabs, SLOT(saveToProfile(QString))); 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); } int sx = group.readEntry("Window Width", -1); int sy = group.readEntry("Window Height", -1); if (sx != -1 && sy != -1) resize(sx, sy); if (group.readEntry("Window Maximized", false)) { setWindowState(windowState() | Qt::WindowMaximized); } if (equalSizes) { int newSize6 = syncList->header()->sectionSize(6); int newSize0 = syncList->header()->sectionSize(0); int delta = newSize6 - newSize0 + (newSize6 & 1); newSize0 += (delta / 2); if (newSize0 > 20) syncList->header()->resizeSection(0, newSize0); } 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; SyncViewItem *syncItem = (SyncViewItem *)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; SyncViewItem *syncItem = (SyncViewItem *)itemIn; if (syncItem == 0) 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++)) != 0) { SyncViewItem *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++)) != 0) { SyncViewItem *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++)) != 0) { SyncViewItem *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", sizeX); group.writeEntry("Window Height", sizeY); 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 = 0; 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 = 0; SyncViewItem *dirItem; if (item->parent() == 0) { 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, QIcon::fromTheme(isDir ? "folder" : "document-new")); if (!item->isMarked()) listItem->setHidden(true); else syncList->scrollTo(syncList->indexOf(listItem)); } } void SynchronizerGUI::markChanged(SynchronizerFileItem *item, bool ensureVisible) { SyncViewItem *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; } SynchronizeDialog *sd = new SynchronizeDialog(this, &synchronizer, copyToLeftNr, copyToLeftSize, copyToRightNr, copyToRightSize, deleteNr, deleteSize, parallelThreadsSpinBox->value()); wasSync = sd->wasSyncronizationStarted(); delete sd; if (wasSync) closeDialog(); } void SynchronizerGUI::resizeEvent(QResizeEvent *e) { if (!isMaximized()) { sizeX = e->size().width(); sizeY = e->size().height(); } if (!firstResize) { int delta = e->size().width() - e->oldSize().width() + (e->size().width() & 1); int newSize = syncList->header()->sectionSize(0) + delta / 2; if (newSize > 20) syncList->header()->resizeSection(0, newSize); } firstResize = false; QDialog::resizeEvent(e); } void SynchronizerGUI::statusInfo(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 == 0) break; bool isedit = e->key() == Qt::Key_F4; SynchronizerFileItem *item = ((SyncViewItem *)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) { QKeyEvent* ke = (QKeyEvent*) 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 == 0) return true; SynchronizerFileItem *item = ((SyncViewItem *)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(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(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) { QPushButton *button = new QPushButton(parent); if (!text.isEmpty() && (textAndIcon || !QIcon::hasThemeIcon(iconName))) button->setText(text); button->setIcon(QIcon::fromTheme(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++)) != 0) { SynchronizerGUI::SyncViewItem *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; QMimeData *mimeData = new QMimeData; mimeData->setImageData(FL_LOADICON(isLeft ? "arrow-left-double" : "arrow-right-double")); 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 4a9c731f..84dd72b5 100644 --- a/krusader/Synchronizer/synchronizergui.h +++ b/krusader/Synchronizer/synchronizergui.h @@ -1,262 +1,252 @@ -/*************************************************************************** - synchronizergui.h - description - ------------------- - copyright : (C) 2003 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2003 Csaba Karai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef SYNCHRONIZERGUI_H #define SYNCHRONIZERGUI_H // QtCore #include // QtGui #include #include #include // QtWidgets #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, QString label1, QString label2 = QString(), QString label3 = QString(), QString label4 = QString(), QString label5 = QString(), QString label6 = QString(), QString label7 = QString(), QString label8 = QString()) : QTreeWidgetItem(parent, after), syncItemRef(item), lastItemRef(0) { 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(txt, base); } SyncViewItem(SynchronizerFileItem *item, QColor txt, QColor base, QTreeWidgetItem * parent, QTreeWidgetItem *after, QString label1, QString label2 = QString(), QString label3 = QString(), QString label4 = QString(), QString label5 = QString(), QString label6 = QString(), QString label7 = QString(), QString label8 = QString()) : QTreeWidgetItem(parent, after), syncItemRef(item), lastItemRef(0) { 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(txt, base); } ~SyncViewItem() { syncItemRef->setUserData(0); } inline SynchronizerFileItem * synchronizerItemRef() { return syncItemRef; } inline SyncViewItem * lastItem() { return lastItemRef; } inline void setLastItem(SyncViewItem*s) { lastItemRef = s; } void setColors(QColor fore, 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(); 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(QString); void saveToProfile(QString); protected slots: void reject(); void addFile(SynchronizerFileItem *); void markChanged(SynchronizerFileItem *, bool); void setScrolling(bool); void statusInfo(QString); void subdirsChecked(bool); void setPanelLabels(); void setCompletion(); void checkExcludeURLValidity(QString &text, QString &error); void connectFilters(const QString &); private: void initGUI(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: virtual void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; virtual bool eventFilter(QObject *, QEvent *) Q_DECL_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 firstResize; bool hasSelectedFiles; SyncViewItem *lastItem; int sizeX; int sizeY; QColor foreGrounds[ TT_MAX ]; QColor backGrounds[ TT_MAX ]; }; #endif /* __SYNCHRONIZERGUI_H__ */ diff --git a/krusader/Synchronizer/synchronizertask.cpp b/krusader/Synchronizer/synchronizertask.cpp index 44a86fa1..742818c5 100644 --- a/krusader/Synchronizer/synchronizertask.cpp +++ b/krusader/Synchronizer/synchronizertask.cpp @@ -1,355 +1,345 @@ -/*************************************************************************** - synchronizertask.cpp - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "synchronizertask.h" // QtCore #include #include #include #include #include "synchronizer.h" #include "synchronizerfileitem.h" #include "synchronizerdirlist.h" #include "../FileSystem/filesystem.h" CompareTask::CompareTask(SynchronizerFileItem *parentIn, const QString &leftURL, const QString &rightURL, const QString &leftDir, const QString &rightDir, bool hidden) : SynchronizerTask(), m_parent(parentIn), m_url(leftURL), m_dir(leftDir), m_otherUrl(rightURL), m_otherDir(rightDir), m_duplicate(true), m_dirList(0), m_otherDirList(0) { ignoreHidden = hidden; } CompareTask::CompareTask(SynchronizerFileItem *parentIn, const QString &urlIn, const QString &dirIn, bool isLeftIn, bool hidden) : SynchronizerTask(), m_parent(parentIn), m_url(urlIn), m_dir(dirIn), m_isLeft(isLeftIn), m_duplicate(false), m_dirList(0), m_otherDirList(0) { ignoreHidden = hidden; } CompareTask::~CompareTask() { if (m_dirList) { delete m_dirList; m_dirList = 0; } if (m_otherDirList) { delete m_otherDirList; m_otherDirList = 0; } } void CompareTask::start() { if (m_state == ST_STATE_NEW) { m_state = ST_STATE_PENDING; m_loadFinished = m_otherLoadFinished = false; m_dirList = new SynchronizerDirList(parentWidget, ignoreHidden); connect(m_dirList, SIGNAL(finished(bool)), this, SLOT(slotFinished(bool))); m_dirList->load(m_url, false); if (m_duplicate) { m_otherDirList = new SynchronizerDirList(parentWidget, ignoreHidden); connect(m_otherDirList, SIGNAL(finished(bool)), this, SLOT(slotOtherFinished(bool))); m_otherDirList->load(m_otherUrl, false); } } } void CompareTask::slotFinished(bool result) { if (!result) { m_state = ST_STATE_ERROR; return; } m_loadFinished = true; if (m_otherLoadFinished || !m_duplicate) m_state = ST_STATE_READY; } void CompareTask::slotOtherFinished(bool result) { if (!result) { m_state = ST_STATE_ERROR; return; } m_otherLoadFinished = true; if (m_loadFinished) m_state = ST_STATE_READY; } CompareContentTask::CompareContentTask(Synchronizer *syn, SynchronizerFileItem *itemIn, const QUrl &leftURLIn, const QUrl &rightURLIn, KIO::filesize_t sizeIn) : SynchronizerTask(), leftURL(leftURLIn), rightURL(rightURLIn), size(sizeIn), errorPrinted(false), leftReadJob(0), rightReadJob(0), compareArray(), owner(-1), item(itemIn), timer(0), leftFile(0), rightFile(0), received(0), sync(syn) { } CompareContentTask::~CompareContentTask() { abortContentComparing(); if (timer) delete timer; if (leftFile) delete leftFile; if (rightFile) delete rightFile; } void CompareContentTask::start() { m_state = ST_STATE_PENDING; if (leftURL.isLocalFile() && rightURL.isLocalFile()) { leftFile = new QFile(leftURL.path()); if (!leftFile->open(QIODevice::ReadOnly)) { KMessageBox::error(parentWidget, i18n("Error at opening %1.", leftURL.path())); m_state = ST_STATE_ERROR; return; } rightFile = new QFile(rightURL.path()); if (!rightFile->open(QIODevice::ReadOnly)) { KMessageBox::error(parentWidget, i18n("Error at opening %1.", rightURL.path())); m_state = ST_STATE_ERROR; return; } timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(sendStatusMessage())); timer->setSingleShot(true); timer->start(1000); localFileCompareCycle(); } else { leftReadJob = KIO::get(leftURL, KIO::NoReload, KIO::HideProgressInfo); rightReadJob = KIO::get(rightURL, KIO::NoReload, KIO::HideProgressInfo); connect(leftReadJob, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(slotDataReceived(KIO::Job*,QByteArray))); connect(rightReadJob, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(slotDataReceived(KIO::Job*,QByteArray))); connect(leftReadJob, SIGNAL(result(KJob*)), this, SLOT(slotFinished(KJob*))); connect(rightReadJob, SIGNAL(result(KJob*)), this, SLOT(slotFinished(KJob*))); rightReadJob->suspend(); timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(sendStatusMessage())); timer->setSingleShot(true); timer->start(1000); } } void CompareContentTask::localFileCompareCycle() { bool different = false; char leftBuffer[ 1440 ]; char rightBuffer[ 1440 ]; QTime timer; timer.start(); int cnt = 0; while (!leftFile->atEnd() && !rightFile->atEnd()) { int leftBytes = leftFile->read(leftBuffer, sizeof(leftBuffer)); int rightBytes = rightFile->read(rightBuffer, sizeof(rightBuffer)); if (leftBytes != rightBytes) { different = true; break; } if (leftBytes <= 0) break; received += leftBytes; if (memcmp(leftBuffer, rightBuffer, leftBytes)) { different = true; break; } if ((++cnt % 16) == 0 && timer.elapsed() >= 250) break; } if (different) { sync->compareContentResult(item, false); m_state = ST_STATE_READY; return; } if (leftFile->atEnd() && rightFile->atEnd()) { sync->compareContentResult(item, true); m_state = ST_STATE_READY; return; } QTimer::singleShot(0, this, SLOT(localFileCompareCycle())); } void CompareContentTask::slotDataReceived(KIO::Job *job, const QByteArray &data) { int jobowner = (job == leftReadJob) ? 1 : 0; int bufferLen = compareArray.size(); int dataLen = data.size(); if (job == leftReadJob) received += dataLen; if (jobowner == owner) { compareArray.append(data); return; } do { if (bufferLen == 0) { compareArray = QByteArray(data.data(), dataLen); owner = jobowner; break; } int minSize = (dataLen < bufferLen) ? dataLen : bufferLen; for (int i = 0; i != minSize; i++) if (data[i] != compareArray[i]) { abortContentComparing(); return; } if (minSize == bufferLen) { compareArray = QByteArray(data.data() + bufferLen, dataLen - bufferLen); if (dataLen == bufferLen) { owner = -1; return; } owner = jobowner; break; } else { compareArray = QByteArray(compareArray.data() + dataLen, bufferLen - dataLen); return; } } while (false); KIO::TransferJob *otherJob = (job == leftReadJob) ? rightReadJob : leftReadJob; if (otherJob == 0) { if (compareArray.size()) abortContentComparing(); } else { if (!((KIO::TransferJob *)job)->isSuspended()) { ((KIO::TransferJob *)job)->suspend(); otherJob->resume(); } } } void CompareContentTask::slotFinished(KJob *job) { KIO::TransferJob *otherJob = (job == leftReadJob) ? rightReadJob : leftReadJob; if (job == leftReadJob) leftReadJob = 0; else rightReadJob = 0; if (otherJob) otherJob->resume(); if (job->error()) { timer->stop(); abortContentComparing(); } if (job->error() && job->error() != KIO::ERR_USER_CANCELED && !errorPrinted) { errorPrinted = true; KMessageBox::error(parentWidget, i18n("I/O error while comparing file %1 with %2.", leftURL.toDisplayString(QUrl::PreferLocalFile), rightURL.toDisplayString(QUrl::PreferLocalFile))); } if (leftReadJob == 0 && rightReadJob == 0) { if (!compareArray.size()) sync->compareContentResult(item, true); else sync->compareContentResult(item, false); m_state = ST_STATE_READY; } } void CompareContentTask::abortContentComparing() { if (timer) timer->stop(); if (leftReadJob) leftReadJob->kill(KJob::EmitResult); if (rightReadJob) rightReadJob->kill(KJob::EmitResult); if (item->task() >= TT_UNKNOWN) sync->compareContentResult(item, false); m_state = ST_STATE_READY; } void CompareContentTask::sendStatusMessage() { double perc = (size == 0) ? 1. : (double)received / (double)size; int percent = (int)(perc * 10000. + 0.5); QString statstr = QString("%1.%2%3").arg(percent / 100).arg((percent / 10) % 10).arg(percent % 10) + '%'; setStatusMessage(i18n("Comparing file %1 (%2)...", leftURL.fileName(), statstr)); timer->setSingleShot(true); timer->start(500); } diff --git a/krusader/Synchronizer/synchronizertask.h b/krusader/Synchronizer/synchronizertask.h index e49be5ab..2d1f1a75 100644 --- a/krusader/Synchronizer/synchronizertask.h +++ b/krusader/Synchronizer/synchronizertask.h @@ -1,200 +1,190 @@ -/*************************************************************************** - synchronizertask.h - description - ------------------- - copyright : (C) 2006 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2006 Csaba Karai * + * Copyright (C) 2006-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef 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() : QObject(), m_state(ST_STATE_NEW), m_statusMessage(QString()) {} virtual ~SynchronizerTask() {} 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); virtual ~CompareTask(); 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: virtual void start(); 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); virtual ~CompareContentTask(); public slots: void slotDataReceived(KIO::Job *job, const QByteArray &data); void slotFinished(KJob *job); void sendStatusMessage(); protected: virtual void start(); 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/defaults.h b/krusader/defaults.h index 9229a6ea..b31967ff 100644 --- a/krusader/defaults.h +++ b/krusader/defaults.h @@ -1,346 +1,336 @@ -/*************************************************************************** - defaults.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef DEFAULTS_H #define DEFAULTS_H // QtGui #include /////////////////////// [Startup] // UI Save component Settings #define _UiSave true // Show Cmd Line #define _ShowCmdline false // Show status bar #define _ShowStatusBar true // Show actions tool bar #define _ShowActionsToolBar true // Show tool bar #define _ShowToolBar true // Show FN Keys #define _ShowFNkeys true // Show Terminal Emulator #define _ShowTerminalEmulator false // Remember Position #define _RememberPos true // Start to tray #define _StartToTray false // Left Tab Bar // Right Tab Bar // Size where lister is the default viewer #define _ListerLimit 10 ////////////////////////[Look&Feel] // Filelist Font /////// #define _FilelistFont QFontDatabase::systemFont(QFontDatabase::GeneralFont) // Warn On Exit //////// #define _WarnOnExit false // Minimize To Tray //// #define _ShowTrayIcon false // Mark Dirs /////////// #define _MarkDirs false // Show Hidden ///////// #define _ShowHidden true // Sort By Extension /// #define _SortByExt false // Case Sensative Sort / #define _CaseSensativeSort false // Html Min Font Size // #define _HtmlMinFontSize 12 // Filelist Icon Size // #define _FilelistIconSize QString("22") // Mouse Selection ///// #define _MouseSelection 0 // 0 - normal (shift+click, ctrl+click), 1 - left click, 2 - right click // Use fullpath tab names ///// #define _FullPathTabNames false // User defined folder icons #define _UserDefinedFolderIcons true // Always show current item decoration in panel #define _AlwaysShowCurrentItem true // Unslect files before copy/move #define _UnselectBeforeOperation false // Filter dialog remembers settings #define _FilterDialogRemembersSettings false // Panel Toolbar Checkboxes // Panel Toolbar Visible checkbox turned off #define _PanelToolBar true // cd / is turned on #define _cdRoot true // cd ~ is turned on #define _cdHome false // cd .. is turned on #define _cdUp true // cd other panel is turned on #define _cdOther false // syncBrowseButton is turned on #define _syncBrowseButton false // Use the default colors of KDE #define _KDEDefaultColors true // Enable Alternate Background colors #define _AlternateBackground true // Show current item even if not focused #define _ShowCurrentItemAlways false // Dim the colors of the inactive panel #define _DimInactiveColors false // Human Readable Size #define _HumanReadableSize true // With Icons #define _WithIcons true // Single Click Selects #define _SingleClickSelects false // Numeric Permissions #define _NumericPermissions false // Number of Columns in the Brief View #define _NumberOfBriefColumns 3 // Default Sort Method #define _DefaultSortMethod KrViewProperties::Krusader // Show splashscreen #define _ShowSplashScreen false // Single instance mode #define _SingleInstanceMode false /////////////////////// [General] // Move To Trash ////// #define _MoveToTrash true // Terminal /////////// #define _Terminal "konsole --separate" // Send CDs /////////// #define _SendCDs true // Editor ///////////// #define _Editor "internal editor" // Use Okteta as Hex viewer /////// #define _UseOktetaViewer false // Temp Directory ///// #define _TempDirectory "/tmp/krusader.tmp" // Classic Quicksearch #define _NewStyleQuicksearch true // Case Sensitive quick search, if _NewStyleQuicksearch is true #define _CaseSensitiveQuicksearch false // Special handling of Right Arrow in Quicksearch #define _NavigationWithRightArrowQuicksearch true // View In Separate Window #define _ViewInSeparateWindow false /////////////////////// [Advanced] // Permission Check /// //#define _PermCheck true // AutoMount ////////// #define _AutoMount false // Preserving date ////////// #define _PreserveAttributes false // Nonmount Points //// #define _NonMountPoints "/, " // Confirm Unempty Dir // (for delete) #define _ConfirmUnemptyDir true // Confirm Delete ///// (for deleting files) #define _ConfirmDelete true // Confirm Copy /////// (for copying files) #define _ConfirmCopy true // Confirm Move /////// (for moving files) #define _ConfirmMove true // Icon Cache Size //// #define _IconCacheSize 2048 /////////////////////// [Archives] // Do Tar ///////////// #define _DoTar true // Do GZip //////////// #define _DoGZip true // Do Zip ///////////// #define _DoZip true // Do UnZip /////////// #define _DoUnZip true // Do BZip2 /////////// #define _DoBZip2 true // Do LZMA /////////// #define _DoLZMA true // Do XZ /////////// #define _DoXZ true // Do Rar ///////////// #define _DoRar true // Do UnRar /////////// #define _DoUnRar true // Do UnAce /////////// #define _DoUnAce true // Do Arj ///////////// #define _DoArj true // Do UnArj /////////// #define _DoUnarj true // Do RPM ///////////// #define _DoRPM true // Do DEB ///////////// ====> new #define _DoDEB true // Do Lha ///////////// #define _DoLha true // Do 7z ///////////// ====> new #define _Do7z true // Allow Move Into Archive // #define _MoveIntoArchive false // Test Archives ////// #define _TestArchives false // Test Before Unpack //// #define _TestBeforeUnpack true // Supported Packers // ====> a QStringList of SYSTEM supported archives ( also new ) // default compression level #define _defaultCompressionLevel 5 // treat Archives as Directories #define _ArchivesAsDirectories true /////////////////////// [UserActions] // Terminal for UserActions /////////// #define _UserActions_Terminal "konsole --noclose --workdir %d --title %t -e" // Normal font for output collection /////// #define _UserActions_NormalFont QFontDatabase::systemFont(QFontDatabase::GeneralFont) // Font for output collection with fixed width /////// #define _UserActions_FixedFont QFontDatabase::systemFont(QFontDatabase::FixedFont) // Use for output collection fixed width font as default /////// #define _UserActions_UseFixedFont false /////////////////////// [Private] // Start Position ///// #define _StartPosition QPoint(QApplication::desktop()->width()/2 - MAIN_VIEW->sizeHint().width()/2,QApplication::desktop()->height()/2 - 250) // Start Size ///////// #define _StartSize QSize(MAIN_VIEW->sizeHint().width(),500) // Panel Size ///////// #define _PanelSize 0 // Terminal Size ////// #define _TerminalSize 0 // Left Name Size - size of the left panel's name column // Left Size Size - size of the left panel's size column // Left Date Size - size of the left panel's date column // Right Name Size - size of the right panel's name column // Right Size Size - size of the left panel's size column // Right Date Size - size of the left panel's date column // Splitter Sizes - sizes of the splitter /////////////////////// [RemoteMan] // Connections //////// // the basic connections are defined internally /////////////////////// [Search] // Saved Searches ///// // holds an index of saved searches // Confirm Feed to Listbox ///// (costum-name on feed ti listbox) #define _ConfirmFeedToListbox true /////////// here are additional variables used internally by Krusader //////////// // BookmarkArchives - The infobox about not allowing bookmarks inside archives // BackArchiveWarning - The infobox about not allowing to back up into archives // SupermountWarning - Warning about mounting/unmounting supermount filesystems // lastHomeRight - Save the last place the right list panel was showing // lastHomeLeft - Save the last place the left list panel was showing // lastUsedPacker - used by packGUI to remember the last used packer /////////////////////// [Popular Urls] // PopularUrls - a string list containing the top urls // PopularUrlsRank - an int list contains the urls' ranking /////////////////////// [Synchronize directories] // Don't overwrite automatically ///////////// #define _ConfirmOverWrites false // Recursive search in the subdirectories ///////////// #define _RecurseSubdirs true // The searcher follows symlinks ///////////// #define _FollowSymlinks false // Files with similar size are compared by content ///////////// #define _CompareByContent false // The date information is ignored at synchronization ///////////// #define _IgnoreDate false // Asymmetric Client-File Server compare mode ///////////// #define _Asymmetric false // Case insensitive compare in synchronizer ///////////// #define _IgnoreCase false // Scrolls the results of the synchronization ///////////// #define _ScrollResults false // The right arrow button is turned on ///////////// #define _BtnLeftToRight true // The equals button is turned on ///////////// #define _BtnEquals true // The not equals button is turned on ///////////// #define _BtnDifferents true // The left arrow button is turned on ///////////// #define _BtnRightToLeft true // The trash button is turned on ///////////// #define _BtnDeletable true // The duplicates button is turned on ///////////// #define _BtnDuplicates true // The singles button is turned on ///////////// #define _BtnSingles true /////////////////////// [Custom Selection Mode] // QT Selection #define _QtSelection false // Left Selects #define _LeftSelects true // Left Preserves #define _LeftPreserves false // ShiftCtrl Left Selects #define _ShiftCtrlLeft false // Right Selects #define _RightSelects true // Right Preserves #define _RightPreserves false // ShiftCtrl Right Selects #define _ShiftCtrlRight false // Space Moves Down #define _SpaceMovesDown true // Space Calc Space #define _SpaceCalcSpace true // Insert Moves Down #define _InsertMovesDown true // Immediate Context Menu #define _ImmediateContextMenu true // Root directory #ifdef Q_WS_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/kractions.cpp b/krusader/kractions.cpp index d90af7a8..652aeb2c 100644 --- a/krusader/kractions.cpp +++ b/krusader/kractions.cpp @@ -1,333 +1,324 @@ -/*************************************************************************** - kractions.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "kractions.h" // QtWidgets #include #include #include #include #include #include #include #include #include "defaults.h" #include "krusader.h" #include "krusaderview.h" #include "krslots.h" #include "krtrashhandler.h" #include "Dialogs/popularurls.h" #include "GUI/krremoteencodingmenu.h" #include "JobMan/jobman.h" #include "MountMan/kmountman.h" #include "Panel/PanelView/krviewfactory.h" #include "UserAction/useraction.h" QAction *KrActions::actCompare = 0; QAction *KrActions::actDiskUsage = 0; QAction *KrActions::actHomeTerminal = 0; QAction *KrActions::actRemoteEncoding = 0; QAction *KrActions::actProfiles = 0; QAction *KrActions::actMultiRename = 0; QAction *KrActions::actMountMan = 0; QAction *KrActions::actNewTool = 0; QAction *KrActions::actKonfigurator = 0; QAction *KrActions::actToolsSetup = 0; QAction *KrActions::actSwapPanels = 0; QAction *KrActions::actSwapSides = 0; QAction *KrActions::actFind = 0; QAction *KrActions::actLocate = 0; QAction *KrActions::actSwitchFullScreenTE = 0; QAction *KrActions::actAddBookmark = 0; QAction *KrActions::actSavePosition = 0; QAction *KrActions::actSelectColorMask = 0; QAction *KrActions::actOpenLeftBm = 0; QAction *KrActions::actOpenRightBm = 0; QAction *KrActions::actCmdlinePopup = 0; QAction *KrActions::actSplit = 0; QAction *KrActions::actCombine = 0; QAction *KrActions::actUserMenu = 0; QAction *KrActions::actManageUseractions = 0; #ifdef SYNCHRONIZER_ENABLED QAction *KrActions::actSyncDirs = 0; #endif QAction *KrActions::actF10Quit = 0; QAction *KrActions::actEmptyTrash = 0; QAction *KrActions::actTrashBin = 0; QAction *KrActions::actPopularUrls = 0; KToggleAction *KrActions::actToggleTerminal = 0; QAction *KrActions::actVerticalMode = 0; QAction *KrActions::actSelectNewerAndSingle = 0; QAction *KrActions::actSelectSingle = 0; QAction *KrActions::actSelectNewer = 0; QAction *KrActions::actSelectDifferentAndSingle = 0; QAction *KrActions::actSelectDifferent = 0; QAction **KrActions::compareArray[] = {&actSelectNewerAndSingle, &actSelectNewer, &actSelectSingle, &actSelectDifferentAndSingle, &actSelectDifferent, 0 }; QAction *KrActions::actExecStartAndForget = 0; QAction *KrActions::actExecCollectSeparate = 0; QAction *KrActions::actExecCollectTogether = 0; QAction *KrActions::actExecTerminalExternal = 0; QAction *KrActions::actExecTerminalEmbedded = 0; QAction **KrActions::execTypeArray[] = {&actExecStartAndForget, &actExecCollectSeparate, &actExecCollectTogether, &actExecTerminalExternal, &actExecTerminalEmbedded, 0 }; KToggleAction *KrActions::actToggleFnkeys = 0; KToggleAction *KrActions::actToggleCmdline = 0; KToggleAction *KrActions::actShowStatusBar = 0; KToggleAction *KrActions::actToggleHidden = 0; KToggleAction *KrActions::actCompareDirs = 0; QAction *KrActions::actJobProgress = 0; QAction *KrActions::actJobControl = 0; QAction *KrActions::actJobMode = 0; QAction *KrActions::actJobUndo = 0; #ifdef __KJSEMBED__ static QAction *actShowJSConsole; #endif QAction *createAction(QString text, QString icon, QKeySequence shortcut, QObject *recv, const char *slot, QString name, Krusader *krusaderApp) { QAction *a; if (icon.isEmpty()) a = new QAction(text, krusaderApp); else a = new QAction(QIcon::fromTheme(icon), text, krusaderApp); krusaderApp->connect(a, SIGNAL(triggered(bool)), recv, slot); krusaderApp->actionCollection()->addAction(name, a); krusaderApp->actionCollection()->setDefaultShortcut(a, shortcut); return a; } QAction *createAction(QString text, QString icon, QList shortcuts, QObject *recv, const char *slot, QString name, Krusader *krusaderApp) { QAction *a; if (icon.isEmpty()) a = new QAction(text, krusaderApp); else a = new QAction(QIcon::fromTheme(icon), text, krusaderApp); krusaderApp->connect(a, SIGNAL(triggered(bool)), recv, slot); krusaderApp->actionCollection()->addAction(name, a); krusaderApp->actionCollection()->setDefaultShortcuts(a, shortcuts); return a; } KToggleAction *createToggleAction(QString text, QString icon, QKeySequence shortcut, QObject *recv, const char *slot, QString name, Krusader *krusaderApp) { KToggleAction *a; if (icon == 0) a = new KToggleAction(text, krusaderApp); else a = new KToggleAction(QIcon::fromTheme(icon), text, krusaderApp); krusaderApp->connect(a, SIGNAL(triggered(bool)), recv, slot); krusaderApp->actionCollection()->addAction(name, a); krusaderApp->actionCollection()->setDefaultShortcut(a, shortcut); return a; } void KrActions::setupActions(Krusader *krusaderApp) { #define NEW_KACTION(VAR, TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME) \ VAR = createAction(TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME, krusaderApp); #define NEW_KTOGGLEACTION(VAR, TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME) \ VAR = createToggleAction(TEXT, ICON_NAME, SHORTCUT, RECV_OBJ, SLOT_NAME, NAME, krusaderApp); // first come the TODO actions //actSync = 0;//new QAction(i18n("S&ynchronize Dirs"), 0, krusaderApp, 0, actionCollection(), "sync dirs"); //actNewTool = 0;//new QAction(i18n("&Add a new tool"), 0, krusaderApp, 0, actionCollection(), "add tool"); //actToolsSetup = 0;//new QAction(i18n("&Tools Menu Setup"), 0, 0, krusaderApp, 0, actionCollection(), "tools setup"); //KStandardAction::print(SLOTS, 0,actionCollection(),"std_print"); //KStandardAction::showMenubar( SLOTS, SLOT(showMenubar()), actionCollection(), "std_menubar" ); /* Shortcut disabled because of the Terminal Emulator bug. */ KConfigGroup group(krConfig, "Private"); int compareMode = group.readEntry("Compare Mode", 0); int cmdExecMode = group.readEntry("Command Execution Mode", 0); QAction *tmp; Q_UNUSED(tmp); NEW_KACTION(tmp, i18n("Tab-Switch panel"), 0, Qt::Key_Tab, MAIN_VIEW, SLOT(panelSwitch()), "tab"); KToggleToolBarAction *actShowToolBar = new KToggleToolBarAction(krusaderApp->toolBar(), i18n("Show Main Toolbar"), krusaderApp); krusaderApp->actionCollection()->addAction(KStandardAction::name(KStandardAction::ShowToolbar), actShowToolBar); KToggleToolBarAction *actShowJobToolBar = new KToggleToolBarAction(krusaderApp->toolBar("jobToolBar"), i18n("Show Job Toolbar"), krusaderApp); krusaderApp->actionCollection()->addAction("toggle show jobbar", actShowJobToolBar); KToggleToolBarAction *actShowActionsToolBar = new KToggleToolBarAction(krusaderApp->toolBar("actionsToolBar"), i18n("Show Actions Toolbar"), krusaderApp); krusaderApp->actionCollection()->addAction("toggle actions toolbar", actShowActionsToolBar); actShowStatusBar = KStandardAction::showStatusbar(SLOTS, SLOT(updateStatusbarVisibility()), krusaderApp->actionCollection()); KStandardAction::quit(krusaderApp, SLOT(quit()), krusaderApp->actionCollection()); KStandardAction::configureToolbars(krusaderApp, SLOT(configureToolbars()), krusaderApp->actionCollection()); KStandardAction::keyBindings(krusaderApp->guiFactory(), SLOT(configureShortcuts()), krusaderApp->actionCollection()); // the toggle actions NEW_KTOGGLEACTION(actToggleFnkeys, i18n("Show &FN Keys Bar"), 0, 0, SLOTS, SLOT(toggleFnkeys()), "toggle fn bar"); NEW_KTOGGLEACTION(actToggleCmdline, i18n("Show &Command Line"), 0, 0, SLOTS, SLOT(toggleCmdline()), "toggle command line"); NEW_KTOGGLEACTION(actToggleTerminal, i18n("Show &Embedded Terminal"), 0, Qt::ALT + Qt::CTRL + Qt::Key_T, SLOTS, SLOT(toggleTerminal()), "toggle terminal emulator"); NEW_KTOGGLEACTION(actToggleHidden, i18n("Show &Hidden Files"), 0, Qt::ALT + Qt::Key_Period, SLOTS, SLOT(showHiddenFiles(bool)), "toggle hidden files"); NEW_KACTION(actSwapPanels, i18n("S&wap Panels"), 0, Qt::CTRL + Qt::Key_U, SLOTS, SLOT(swapPanels()), "swap panels"); NEW_KACTION(actEmptyTrash, i18n("Empty Trash"), "trash-empty", 0, SLOTS, SLOT(emptyTrash()), "emptytrash"); NEW_KACTION(actTrashBin, i18n("Trash Popup Menu"), KrTrashHandler::trashIcon(), 0, SLOTS, SLOT(trashPopupMenu()), "trashbin"); NEW_KACTION(actSwapSides, i18n("Sw&ap Sides"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_U, SLOTS, SLOT(toggleSwapSides()), "toggle swap sides"); actToggleHidden->setChecked(KConfigGroup(krConfig, "Look&Feel").readEntry("Show Hidden", _ShowHidden)); // and then the DONE actions NEW_KACTION(actCmdlinePopup, i18n("popup cmdline"), 0, Qt::CTRL + Qt::Key_Slash, SLOTS, SLOT(cmdlinePopup()), "cmdline popup"); NEW_KACTION(tmp, i18n("Start &Root Mode Krusader"), "krusader_root", Qt::ALT + Qt::SHIFT + Qt::Key_K, SLOTS, SLOT(rootKrusader()), "root krusader"); NEW_KACTION(actProfiles, i18n("Pro&files"), "user-identity", Qt::ALT + Qt::SHIFT + Qt::Key_L, MAIN_VIEW, SLOT(profiles()), "profile"); NEW_KACTION(actSplit, i18n("Sp&lit File..."), "split", Qt::CTRL + Qt::Key_P, SLOTS, SLOT(slotSplit()), "split"); NEW_KACTION(actCombine, i18n("Com&bine Files..."), "kr_combine", 0, SLOTS, SLOT(slotCombine()), "combine"); NEW_KACTION(actSelectNewerAndSingle, i18n("&Select Newer and Single"), 0, 0, SLOTS, SLOT(compareSetup()), "select_newer_and_single"); NEW_KACTION(actSelectNewer, i18n("Select &Newer"), 0, 0, SLOTS, SLOT(compareSetup()), "select_newer"); NEW_KACTION(actSelectSingle, i18n("Select &Single"), 0, 0, SLOTS, SLOT(compareSetup()), "select_single"); NEW_KACTION(actSelectDifferentAndSingle, i18n("Select Different &and Single"), 0, 0, SLOTS, SLOT(compareSetup()), "select_different_and_single"); NEW_KACTION(actSelectDifferent, i18n("Select &Different"), 0, 0, SLOTS, SLOT(compareSetup()), "select_different"); actSelectNewerAndSingle->setCheckable(true); actSelectNewer->setCheckable(true); actSelectSingle->setCheckable(true); actSelectDifferentAndSingle->setCheckable(true); actSelectDifferent->setCheckable(true); QActionGroup *selectGroup = new QActionGroup(krusaderApp); selectGroup->setExclusive(true); selectGroup->addAction(actSelectNewerAndSingle); selectGroup->addAction(actSelectNewer); selectGroup->addAction(actSelectSingle); selectGroup->addAction(actSelectDifferentAndSingle); selectGroup->addAction(actSelectDifferent); if (compareMode < (int)(sizeof(compareArray) / sizeof(QAction **)) - 1) (*compareArray[ compareMode ])->setChecked(true); NEW_KACTION(actExecStartAndForget, i18n("Start and &Forget"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_start_and_forget"); NEW_KACTION(actExecCollectSeparate, i18n("Display &Separated Standard and Error Output"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_collect_separate"); NEW_KACTION(actExecCollectTogether, i18n("Display &Mixed Standard and Error Output"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_collect_together"); NEW_KACTION(actExecTerminalExternal, i18n("Start in &New Terminal"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_terminal_external"); NEW_KACTION(actExecTerminalEmbedded, i18n("Send to &Embedded Terminal Emulator"), 0, 0, SLOTS, SLOT(execTypeSetup()), "exec_terminal_embedded"); actExecStartAndForget->setCheckable(true); actExecCollectSeparate->setCheckable(true); actExecCollectTogether->setCheckable(true); actExecTerminalExternal->setCheckable(true); actExecTerminalEmbedded->setCheckable(true); QActionGroup *actionGroup = new QActionGroup(krusaderApp); actionGroup->setExclusive(true); actionGroup->addAction(actExecStartAndForget); actionGroup->addAction(actExecCollectSeparate); actionGroup->addAction(actExecCollectTogether); actionGroup->addAction(actExecTerminalExternal); actionGroup->addAction(actExecTerminalEmbedded); if (cmdExecMode < (int)(sizeof(execTypeArray) / sizeof(QAction **)) - 1) (*execTypeArray[ cmdExecMode ])->setChecked(true); NEW_KACTION(actHomeTerminal, i18n("Start &Terminal"), "utilities-terminal", 0, SLOTS, SLOT(homeTerminal()), "terminal@home"); actMountMan = krMtMan.action(); krusaderApp->actionCollection()->addAction("mountman", actMountMan); krusaderApp->actionCollection()->setDefaultShortcut(actMountMan, Qt::ALT + Qt::Key_Slash); NEW_KACTION(actFind, i18n("&Search..."), "system-search", Qt::CTRL + Qt::Key_S, SLOTS, SLOT(search()), "find"); NEW_KACTION(actLocate, i18n("&Locate..."), "edit-find", Qt::SHIFT + Qt::CTRL + Qt::Key_L, SLOTS, SLOT(locate()), "locate"); #ifdef SYNCHRONIZER_ENABLED NEW_KACTION(actSyncDirs, i18n("Synchronize Fol&ders..."), "folder-sync", Qt::CTRL + Qt::Key_Y, SLOTS, SLOT(slotSynchronizeDirs()), "sync dirs"); #endif NEW_KACTION(actDiskUsage, i18n("D&isk Usage..."), "kr_diskusage", Qt::ALT + Qt::SHIFT + Qt::Key_S, SLOTS, SLOT(slotDiskUsage()), "disk usage"); NEW_KACTION(actKonfigurator, i18n("Configure &Krusader..."), "configure", 0, SLOTS, SLOT(startKonfigurator()), "konfigurator"); NEW_KACTION(actSavePosition, i18n("Save &Position"), 0, 0, krusaderApp, SLOT(savePosition()), "save position"); NEW_KACTION(actCompare, i18n("Compare b&y Content..."), "kr_comparedirs", 0, SLOTS, SLOT(compareContent()), "compare"); NEW_KACTION(actMultiRename, i18n("Multi &Rename..."), "edit-rename", Qt::SHIFT + Qt::Key_F9, SLOTS, SLOT(multiRename()), "multirename"); NEW_KACTION(actAddBookmark, i18n("Add Bookmark"), "bookmark-new", KStandardShortcut::addBookmark(), SLOTS, SLOT(addBookmark()), "add bookmark"); NEW_KACTION(actVerticalMode, i18n("Vertical Mode"), "view-split-top-bottom", Qt::ALT + Qt::CTRL + Qt::Key_R, MAIN_VIEW, SLOT(toggleVerticalMode()), "toggle vertical mode"); actUserMenu = new KActionMenu(i18n("User&actions"), krusaderApp); krusaderApp->actionCollection()->addAction("useractionmenu", actUserMenu); NEW_KACTION(actManageUseractions, i18n("Manage User Actions..."), 0, 0, SLOTS, SLOT(manageUseractions()), "manage useractions"); actRemoteEncoding = new KrRemoteEncodingMenu(i18n("Select Remote Charset"), "character-set", krusaderApp->actionCollection()); NEW_KACTION(actF10Quit, i18n("Quit"), 0, Qt::Key_F10, krusaderApp, SLOT(quit()) , "F10_Quit"); actF10Quit->setToolTip(i18n("Quit Krusader.")); NEW_KACTION(actPopularUrls, i18n("Popular URLs..."), 0, Qt::CTRL + Qt::Key_Z, krusaderApp->popularUrls(), SLOT(showDialog()), "Popular_Urls"); NEW_KACTION(actSwitchFullScreenTE, i18n("Toggle Fullscreen Embedded Terminal"), 0, Qt::CTRL + Qt::ALT + Qt::Key_F, MAIN_VIEW, SLOT(toggleFullScreenTerminalEmulator()), "switch_fullscreen_te"); NEW_KACTION(tmp, i18n("Move Focus Up"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Up, MAIN_VIEW, SLOT(focusUp()), "move_focus_up"); NEW_KACTION(tmp, i18n("Move Focus Down"), 0, Qt::CTRL + Qt::SHIFT + Qt::Key_Down, MAIN_VIEW, SLOT(focusDown()), "move_focus_down"); // job manager actions actJobControl = krJobMan->controlAction(); krusaderApp->actionCollection()->addAction("job control", actJobControl); krusaderApp->actionCollection()->setDefaultShortcut(actJobControl, Qt::CTRL + Qt::ALT + Qt::Key_P); actJobProgress = krJobMan->progressAction(); krusaderApp->actionCollection()->addAction("job progress", actJobProgress); actJobMode = krJobMan->modeAction(); krusaderApp->actionCollection()->addAction("job mode", actJobMode); actJobUndo = krJobMan->undoAction(); krusaderApp->actionCollection()->addAction("job undo", actJobUndo); krusaderApp->actionCollection()->setDefaultShortcut(actJobUndo, Qt::CTRL + Qt::ALT + Qt::Key_Z); // and at last we can set the tool-tips actKonfigurator->setToolTip(i18n("Setup Krusader the way you like it")); actFind->setToolTip(i18n("Search for files")); // setup all UserActions krUserAction = new UserAction(); #ifdef __KJSEMBED__ actShowJSConsole = new QAction(i18n("JavaScript Console..."), Qt::ALT + Qt::CTRL + Qt::Key_J, SLOTS, SLOT(jsConsole()), krusaderApp->actionCollection(), "JS_Console"); #endif } diff --git a/krusader/kractions.h b/krusader/kractions.h index 5552412a..bcd8d17f 100644 --- a/krusader/kractions.h +++ b/krusader/kractions.h @@ -1,120 +1,110 @@ -/*************************************************************************** - kractions.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRACTIONS_H #define KRACTIONS_H // QtCore #include // QtWidgets #include #include class Krusader; class KrActions : public QObject { Q_OBJECT public: explicit KrActions(QObject *parent) : QObject(parent) {} // Actions static QAction *actCompare; static QAction *actCmdlinePopup, *actLocate, *actSwitchFullScreenTE; static QAction *actDiskUsage, *actSavePosition; static QAction *actHomeTerminal, *actProfiles; static QAction *actMountMan, *actNewTool, *actSwapPanels, *actSwapSides; static QAction *actKonfigurator, *actToolsSetup, *actFind; static QAction *actRemoteEncoding; static QAction *actSelectColorMask, *actMultiRename, *actOpenLeftBm, *actOpenRightBm, *actAddBookmark; static QAction *actSplit; static QAction *actCombine; static QAction *actUserMenu; static QAction *actManageUseractions; #ifdef SYNCHRONIZER_ENABLED static QAction *actSyncDirs; #endif static QAction *actVerticalMode; static QAction *actEmptyTrash, *actTrashBin; static QAction *actPopularUrls; static KToggleAction *actToggleTerminal; static QAction *actSelectNewerAndSingle, *actSelectNewer, *actSelectSingle, *actSelectDifferentAndSingle, *actSelectDifferent; static QAction *actF10Quit; /** actions for setting the execution mode of commands from commanddline */ static QAction *actExecStartAndForget, *actExecCollectSeparate, *actExecCollectTogether, *actExecTerminalExternal, *actExecTerminalEmbedded; static KToggleAction *actToggleFnkeys, *actToggleCmdline, *actShowStatusBar, *actToggleHidden, *actCompareDirs; static QAction **compareArray[]; /** actions for setting the execution mode of commands from commanddline */ static QAction **execTypeArray[]; /** JobMan toolbar actions */ static QAction *actJobProgress; static QAction *actJobControl; static QAction *actJobMode; static QAction *actJobUndo; #ifdef __KJSEMBED__ static QAction *actShowJSConsole; #endif static void setupActions(Krusader *krusader); }; // krusader's actions - things krusader can do! #define krHomeTerm KrActions::actHomeTerminal // open terminal@home dir #define krRemoteEncoding KrActions::actRemoteEncoding // remote encoding menu #define krMountMan KrActions::actMountMan // run Mount-manager #define krNewTool KrActions::actNewTool // Add a new tool to menu #define krKonfigurator KrActions::actKonfigurator #define krToolsSetup KrActions::actToolsSetup // setup the tools menu #define krRoot KrActions::actRoot #define krFind KrActions::actFind // find files #define krMultiRename KrActions::actMultiRename //#define krToggleSortByExt KrActions::actToggleSortByExt// Sort by extension #define krSwitchFullScreenTE KrActions::actSwitchFullScreenTE #define krCmdlinePopup KrActions::actCmdlinePopup #define krSplit KrActions::actSplit #define krCombine KrActions::actCombine #define krUserMenu KrActions::actUserMenu #define krPopularUrls KrActions::actPopularUrls #ifdef __KJSEMBED__ #define krJSConsole KrActions::actShowJSConsole #endif #endif diff --git a/krusader/krdebuglogger.cpp b/krusader/krdebuglogger.cpp index be524fda..5b5d4313 100644 --- a/krusader/krdebuglogger.cpp +++ b/krusader/krdebuglogger.cpp @@ -1,54 +1,58 @@ -/*************************************************************************** - krdebuglogger.cpp - ------------------ - copyright : (C) 2016 by Rafi Yanai & Shie Erlich - email : krusader@users.sf.net - web site : http://krusader.sourceforge.net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2016 Rafi Yanai * + * Copyright (C) 2016 Shie Erlich * + * Copyright (C) 2016-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krdebuglogger.h" int KrDebugLogger::indentation = 1; const int KrDebugLogger::indentationIncrease = 3; const QString KrDebugLogger::logFile = QDir::tempPath() + "/krdebug"; KrDebugLogger::KrDebugLogger(const QString &argFunction, int line) : function(argFunction) { QFile file; QTextStream stream; prepareWriting(file, stream); stream << QString("┏"); // Indicates that a function has been started stream << function << "(" << line << ")" << endl; indentation += indentationIncrease; } KrDebugLogger::~KrDebugLogger() { indentation -= indentationIncrease; QFile file; QTextStream stream; prepareWriting(file, stream); stream << QString("┗"); // Indicates that a function is going to finish stream << function << endl; } //! Prepares some elements before a writing into the krarc debug log file void KrDebugLogger::prepareWriting(QFile &file, QTextStream &stream) { file.setFileName(logFile); file.open(QIODevice::WriteOnly | QIODevice::Append); stream.setDevice(&file); stream << "Pid:" << (int)getpid(); // Applies the indentation level to make logs clearer for (int x = 0; x < indentation; ++x) stream << " "; } diff --git a/krusader/krdebuglogger.h b/krusader/krdebuglogger.h index 6511ab1a..862fb462 100644 --- a/krusader/krdebuglogger.h +++ b/krusader/krdebuglogger.h @@ -1,64 +1,68 @@ -/*************************************************************************** - krdebuglogger.h - ------------------ - copyright : (C) 2016 by Rafi Yanai & Shie Erlich - email : krusader@users.sf.net - web site : http://krusader.sourceforge.net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2016 Rafi Yanai * + * Copyright (C) 2016 Shie Erlich * + * Copyright (C) 2016-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRDEBUGLOGGER_H #define KRDEBUGLOGGER_H // QtCore #include #include #include #include //! A class to manage some aspects of the writing of messages into the Krusader debug log file class KrDebugLogger { private: QString function; //! The name of a function which is going to be written about static int indentation; //! The indentation that is presently used, it represents how many spaces are going to be used const static int indentationIncrease; //! The quantity of spaces that are going be added to the indentation when increasing it static const QString logFile; //! The name of the log file public: //! This constructor is used inside the KRFUNC macro. For more details: the description of the KRFUNC macro can be seen KrDebugLogger(const QString &argFunction, int line); //! For more information: the description of the KRFUNC macro can be seen ~KrDebugLogger(); static void prepareWriting(QFile &, QTextStream &); }; #ifdef QT_DEBUG //! Writes a function name, etc. in the Krusader debug log when entering the function and automatically before exiting from it #define KRFUNC \ KrDebugLogger functionLogger(__FUNCTION__, __LINE__); #define KRDEBUG(X...) do{ \ QFile file; \ QTextStream stream; \ KrDebugLogger::prepareWriting(file, stream); \ stream << __FUNCTION__ << "(" <<__LINE__<< "): "; \ stream << X << endl; \ } while(0); #else #define KRFUNC #define KRDEBUG(X...) qDebug() << X #endif #endif // KRDEBUGLOGGER_H diff --git a/krusader/krglobal.cpp b/krusader/krglobal.cpp index e2ec04e5..8048c1b2 100644 --- a/krusader/krglobal.cpp +++ b/krusader/krglobal.cpp @@ -1,72 +1,63 @@ -/*************************************************************************** - krglobal.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krglobal.h" #include "krusader.h" #include "krusaderview.h" // QtCore #include #include KConfig *KrGlobal::config = 0; KMountMan *KrGlobal::mountMan = 0; KrBookmarkHandler *KrGlobal::bookman = 0; KRslots* KrGlobal::slot = 0; KIconLoader *KrGlobal::iconLoader = 0; KrusaderView *KrGlobal::mainView = 0; QWidget *KrGlobal::mainWindow = 0; UserAction *KrGlobal::userAction = 0; JobMan *KrGlobal::jobMan = 0; // ListPanel *KrGlobal::activePanel = 0; QKeySequence KrGlobal::copyShortcut; const int KrGlobal::sConfigVersion; int KrGlobal::sCurrentConfigVersion; KrPanel *KrGlobal::activePanel() { return mainView->activePanel(); } // void KrGlobal::enableAction(const char *name, bool enable) // { // getAction(name)->setEnabled(enable); // } // // QAction* KrGlobal::getAction(const char *name) // { // QAction *act = krApp->actionCollection()->action(name); // if(!act) // qFatal("no such action: %s", name); // return act; // } diff --git a/krusader/krglobal.h b/krusader/krglobal.h index 1081fff6..fad27e60 100644 --- a/krusader/krglobal.h +++ b/krusader/krglobal.h @@ -1,106 +1,96 @@ -/*************************************************************************** - krglobal.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRGLOBAL_H #define KRGLOBAL_H // QtGui #include #include class KConfig; class KMountMan; class KrBookmarkHandler; class KRslots; class KIconLoader; class KrusaderView; class UserAction; class JobMan; class QWidget; class KrPanel; // global references to frequently used objects class KrGlobal { public: static KConfig *config; // allow everyone to access the config static KMountMan *mountMan; // krusader's Mount Manager static KrBookmarkHandler *bookman; static KRslots *slot; static KIconLoader *iconLoader; // the app's icon loader static KrusaderView *mainView; // The GUI static QWidget *mainWindow; static UserAction *userAction; static JobMan *jobMan; // static ListPanel *activePanel; static KrPanel *activePanel(); //HACK - used by [ListerTextArea|KrSearchDialog|LocateDlg]:keyPressEvent() static QKeySequence copyShortcut; // static void enableAction(const char *name, bool enable); // static QAction *getAction(const char *name); /** Version of saved configuration. Use this to detect configuration updates. */ static const int sConfigVersion = 1; static int sCurrentConfigVersion; }; #define krConfig KrGlobal::config #define krMtMan (*(KrGlobal::mountMan)) #define krBookMan KrGlobal::bookman #define SLOTS KrGlobal::slot #define krLoader KrGlobal::iconLoader #define MAIN_VIEW KrGlobal::mainView #define krMainWindow KrGlobal::mainWindow #define krUserAction KrGlobal::userAction #define krJobMan KrGlobal::jobMan #define ACTIVE_PANEL (KrGlobal::activePanel()) #define ACTIVE_MNG (MAIN_VIEW->activeManager()) #define ACTIVE_FUNC (ACTIVE_PANEL->func) #define OTHER_MNG (MAIN_VIEW->inactiveManager()) #define OTHER_PANEL (ACTIVE_PANEL->otherPanel()) #define OTHER_FUNC (OTHER_PANEL->func) #define LEFT_PANEL (MAIN_VIEW->leftPanel()) #define LEFT_FUNC (LEFT_PANEL->func) #define LEFT_MNG (MAIN_VIEW->leftManager()) #define RIGHT_PANEL (MAIN_VIEW->rightPanel()) #define RIGHT_FUNC (RIGHT_PANEL->func) #define RIGHT_MNG (MAIN_VIEW->rightManager()) // #define krEnableAction(name, enable) (KrGlobal::enableAction(#name, (enable))) // #define krGetAction(name) (KrGlobal::getAction(#name)) #endif diff --git a/krusader/krslots.cpp b/krusader/krslots.cpp index 3965b02e..b561144f 100644 --- a/krusader/krslots.cpp +++ b/krusader/krslots.cpp @@ -1,756 +1,747 @@ -/*************************************************************************** - krslots.cpp - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krslots.h" // QtCore #include #include #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #ifdef __KJSEMBED__ #include #include "KrJS/krjs.h" #endif #include "defaults.h" #include "kractions.h" #include "krservices.h" #include "krtrashhandler.h" #include "krusader.h" #include "krusaderview.h" #include "panelmanager.h" #include "ActionMan/actionman.h" #include "BookMan/krbookmarkbutton.h" #include "BookMan/krbookmarkhandler.h" #include "Dialogs/krdialogs.h" #include "Dialogs/krspecialwidgets.h" #include "Dialogs/krspwidgets.h" #include "DiskUsage/diskusagegui.h" #include "FileSystem/fileitem.h" #include "FileSystem/filesystem.h" #include "FileSystem/krquery.h" #include "GUI/dirhistorybutton.h" #include "GUI/kcmdline.h" #include "GUI/kfnkeys.h" #include "GUI/krusaderstatus.h" #include "GUI/mediabutton.h" #include "GUI/terminaldock.h" #include "KViewer/krviewer.h" #include "Konfigurator/konfigurator.h" #include "Locate/locate.h" #include "MountMan/kmountman.h" #include "Panel/PanelView/krselectionmode.h" #include "Panel/PanelView/krview.h" #include "Panel/PanelView/krviewfactory.h" #include "Panel/PanelView/krviewitem.h" #include "Panel/listpanel.h" #include "Panel/panelfunc.h" #include "Panel/sidebar.h" #include "Search/krsearchdialog.h" #include "Search/krsearchmod.h" #include "Splitter/combiner.h" #include "Splitter/splitter.h" #include "Splitter/splittergui.h" #ifdef SYNCHRONIZER_ENABLED #include "Synchronizer/synchronizergui.h" #endif #define ACTIVE_VIEW _mainWindow->activeView() KRslots::KRslots(QObject *parent) : QObject(parent), _mainWindow(krApp) { } void KRslots::sendFileByEmail(const QList &urls) { if (urls.count() == 0) { KMessageBox::error(0, i18n("No selected files to send.")); return; } QString mailProg; QStringList lst = KrServices::supportedTools(); if (lst.contains("MAIL")) mailProg = lst[lst.indexOf("MAIL") + 1]; else { KMessageBox::error(0, i18n("Krusader cannot find a supported mail client. Please install one to your path. Hint: Krusader supports KMail.")); return; } QString subject, separator; foreach(const QUrl &url, urls) { subject += separator + url.fileName(); separator = ','; } subject = i18np("Sending file: %2", "Sending files: %2", urls.count(), subject); KProcess proc; QString executable = QUrl::fromLocalFile(mailProg).fileName(); if (executable == QStringLiteral("kmail")) { proc << mailProg << "--subject" << subject; foreach(const QUrl &url2, urls) proc << "--attach" << url2.toDisplayString(); } else if (executable == QStringLiteral("thunderbird")) { QString param = "attachment=\'"; separator = ""; foreach(const QUrl &url2, urls) { param += separator + url2.toDisplayString(); separator = ','; } param += "\',subject=\'" + subject + "\'"; proc << mailProg << "--compose" << param; } else if (executable == QStringLiteral("evolution")) { QString param = "mailto:?cc=&subject=" + subject + "&attach="; separator = ""; foreach(const QUrl &url2, urls) { param += separator + url2.toDisplayString(); separator = "&attach="; } proc << mailProg << param + ""; } if (!proc.startDetached()) KMessageBox::error(0, i18n("Error executing %1.", mailProg)); } void KRslots::compareContent() { const QStringList lstLeft = LEFT_PANEL->getSelectedNames(); const QStringList lstRight = RIGHT_PANEL->getSelectedNames(); const QStringList lstActive = ACTIVE_PANEL->gui->isLeft() ? lstLeft : lstRight; QUrl name1, name2; if (lstLeft.count() == 1 && lstRight.count() == 1) { // first, see if we've got exactly 1 selected file in each panel: name1 = LEFT_PANEL->func->files()->getUrl(lstLeft[0]); name2 = RIGHT_PANEL->func->files()->getUrl(lstRight[0]); } else if (lstActive.count() == 2) { // next try: are in the current panel exacty 2 files selected? name1 = ACTIVE_PANEL->func->files()->getUrl(lstActive[0]); name2 = ACTIVE_PANEL->func->files()->getUrl(lstActive[1]); } else if (ACTIVE_PANEL->otherPanel()->func->files()->getFileItem(ACTIVE_VIEW->getCurrentItem())) { // next try: is in the other panel a file with the same name? name1 = ACTIVE_PANEL->func->files()->getUrl(ACTIVE_VIEW->getCurrentItem()); name2 = ACTIVE_PANEL->otherPanel()->func->files()->getUrl(ACTIVE_VIEW->getCurrentItem()); } else { // if we got here, then we can't be sure what file to diff KMessageBox::detailedError(0, i18n("Do not know which files to compare."), "" + i18n("To compare two files by content, you can either:
  • Select one file in the left panel, and one in the right panel.
  • Select exactly two files in the active panel.
  • Make sure there is a file in the other panel, with the same name as the current file in the active panel.
") + "
"); return; } // else implied: all ok, let's call an external program to compare files // but if any of the files isn't local, download it first compareContent(name1, name2); } bool downloadToTemp(const QUrl &url, QString &dest) { QTemporaryFile tmpFile; tmpFile.setAutoRemove(false); if (tmpFile.open()) { dest = tmpFile.fileName(); KIO::Job* job = KIO::file_copy(url, QUrl::fromLocalFile(dest), -1, KIO::Overwrite | KIO::HideProgressInfo); if(!job->exec()) { KMessageBox::error(krApp, i18n("Krusader is unable to download %1", url.fileName())); return false; } return true; } return false; } void KRslots::compareContent(QUrl url1, QUrl url2) { QString diffProg; QStringList lst = KrServices::supportedTools(); if (lst.contains("DIFF")) diffProg = lst[lst.indexOf("DIFF") + 1]; else { KMessageBox::error(0, i18n("Krusader cannot find any of the supported diff-frontends. Please install one to your path. Hint: Krusader supports Kompare, KDiff3 and Xxdiff.")); return; } QString tmp1; QString tmp2; // kdiff3 sucks with spaces if (QUrl::fromLocalFile(diffProg).fileName() == "kdiff3" && !url1.toDisplayString().contains(" ") && !url2.toDisplayString().contains(" ")) { tmp1 = url1.toDisplayString(); tmp2 = url2.toDisplayString(); } else { if (!url1.isLocalFile()) { if (!downloadToTemp(url1, tmp1)) { return; } } else tmp1 = url1.path(); if (!url2.isLocalFile()) { if (!downloadToTemp(url2, tmp2)) { if (tmp1 != url1.path()) QFile::remove(tmp1); return; } } else tmp2 = url2.path(); } KrProcess *p = new KrProcess(tmp1 != url1.path() ? tmp1 : QString(), tmp2 != url2.path() ? tmp2 : QString()); *p << diffProg << tmp1 << tmp2; p->start(); if (!p->waitForStarted()) KMessageBox::error(0, i18n("Error executing %1.", diffProg)); } // GUI toggle slots void KRslots::toggleFnkeys() { if (MAIN_VIEW->fnKeys()->isVisible()) MAIN_VIEW->fnKeys()->hide(); else MAIN_VIEW->fnKeys()->show(); } void KRslots::toggleCmdline() { if (MAIN_VIEW->cmdLine()->isVisible()) MAIN_VIEW->cmdLine()->hide(); else MAIN_VIEW->cmdLine()->show(); } void KRslots::updateStatusbarVisibility() { krApp->statusBar()->setVisible(KrActions::actShowStatusBar->isChecked()); } void KRslots::toggleTerminal() { MAIN_VIEW->setTerminalEmulator(KrActions::actToggleTerminal->isChecked()); } void KRslots::insertFileName(bool fullPath) { QString filename = ACTIVE_VIEW->getCurrentItem(); if (filename.isEmpty()) { return; } if (fullPath) { const QString path = FileSystem::ensureTrailingSlash(ACTIVE_PANEL->virtualPath()) .toDisplayString(QUrl::PreferLocalFile); filename = path + filename; } filename = KrServices::quote(filename); if (MAIN_VIEW->cmdLine()->isVisible() || !MAIN_VIEW->terminalDock()->isTerminalVisible()) { QString current = MAIN_VIEW->cmdLine()->text(); if (current.length() != 0 && !current.endsWith(' ')) current += ' '; MAIN_VIEW->cmdLine()->setText(current + filename); MAIN_VIEW->cmdLine()->setFocus(); } else if (MAIN_VIEW->terminalDock()->isTerminalVisible()) { filename = ' ' + filename + ' '; MAIN_VIEW->terminalDock()->sendInput(filename, false); MAIN_VIEW->terminalDock()->setFocus(); } } void KRslots::refresh(const QUrl &u) { ACTIVE_FUNC->openUrl(u); } void KRslots::runKonfigurator(bool firstTime) { Konfigurator *konfigurator = new Konfigurator(firstTime); connect(konfigurator, SIGNAL(configChanged(bool)), SLOT(configChanged(bool))); //FIXME - no need to exec konfigurator->exec(); delete konfigurator; } void KRslots::configChanged(bool isGUIRestartNeeded) { krConfig->sync(); if (isGUIRestartNeeded) { krApp->setUpdatesEnabled(false); KConfigGroup group(krConfig, "Look&Feel"); FileItem::loadUserDefinedFolderIcons(group.readEntry("Load User Defined Folder Icons", _UserDefinedFolderIcons)); bool leftActive = ACTIVE_PANEL->gui->isLeft(); MAIN_VIEW->leftManager()->slotRecreatePanels(); MAIN_VIEW->rightManager()->slotRecreatePanels(); if(leftActive) LEFT_PANEL->slotFocusOnMe(); else RIGHT_PANEL->slotFocusOnMe(); MAIN_VIEW->fnKeys()->updateShortcuts(); KrSelectionMode::resetSelectionHandler(); krApp->setUpdatesEnabled(true); } krApp->setTray(); // really ugly, but reload the Fn keys just in case - csaba: any better idea? MAIN_VIEW->fnKeys()->updateShortcuts(); const bool showHidden = KConfigGroup(krConfig, "Look&Feel") .readEntry("Show Hidden", KrActions::actToggleHidden->isChecked()); if (showHidden != KrActions::actToggleHidden->isChecked()) { KrActions::actToggleHidden->setChecked(showHidden); MAIN_VIEW->leftManager()->reloadConfig(); MAIN_VIEW->rightManager()->reloadConfig(); } } void KRslots::showHiddenFiles(bool show) { KConfigGroup group(krConfig, "Look&Feel"); group.writeEntry("Show Hidden", show); MAIN_VIEW->leftManager()->reloadConfig(); MAIN_VIEW->rightManager()->reloadConfig(); } void KRslots::swapPanels() { QUrl leftURL = LEFT_PANEL->virtualPath(); QUrl rightURL = RIGHT_PANEL->virtualPath(); LEFT_PANEL->func->openUrl(rightURL); RIGHT_PANEL->func->openUrl(leftURL); } void KRslots::toggleSwapSides() { MAIN_VIEW->swapSides(); } void KRslots::search() { if (KrSearchDialog::SearchDialog != 0) { KConfigGroup group(krConfig, "Search"); if (group.readEntry("Window Maximized", false)) KrSearchDialog::SearchDialog->showMaximized(); else KrSearchDialog::SearchDialog->showNormal(); KrSearchDialog::SearchDialog->raise(); KrSearchDialog::SearchDialog->activateWindow(); } else KrSearchDialog::SearchDialog = new KrSearchDialog(); } void KRslots::locate() { if (!KrServices::cmdExist("locate")) { KMessageBox::error(krApp, i18n("Cannot find the 'locate' command. Please install the " "findutils-locate package of GNU, or set its dependencies in " "Konfigurator")); return; } if (LocateDlg::LocateDialog != 0) { LocateDlg::LocateDialog->showNormal(); LocateDlg::LocateDialog->raise(); LocateDlg::LocateDialog->activateWindow(); LocateDlg::LocateDialog->reset(); } else LocateDlg::LocateDialog = new LocateDlg(); } void KRslots::runTerminal(const QString & dir) { KProcess proc; proc.setWorkingDirectory(dir); KConfigGroup group(krConfig, "General"); QString term = group.readEntry("Terminal", _Terminal); QStringList sepdArgs = KShell::splitArgs(term, KShell::TildeExpand); if (sepdArgs.isEmpty()) { KMessageBox::error(krMainWindow, i18nc("Arg is a string containing the bad quoting.", "Bad quoting in terminal command:\n%1", term)); return; } for (int i = 0; i < sepdArgs.size(); i++) { if (sepdArgs[i] == "%d") { sepdArgs[i] = dir; } } proc << sepdArgs; if (!proc.startDetached()) KMessageBox::sorry(krApp, i18n("Error executing %1.", term)); } void KRslots::homeTerminal() { runTerminal(QDir::homePath()); } void KRslots::multiRename() { QStringList lst = KrServices::supportedTools(); int i = lst.indexOf("RENAME"); if (i == -1) { KMessageBox::sorry(krApp, i18n("Cannot find a batch rename tool.\nYou can get KRename at http://www.krename.net")); return; } QString pathToRename = lst[i+1]; const QStringList names = ACTIVE_PANEL->gui->getSelectedNames(); if (names.isEmpty()) { return; } KProcess proc; proc << pathToRename; for (const QString name: names) { FileItem *file = ACTIVE_FUNC->files()->getFileItem(name); if (!file) continue; const QUrl url = file->getUrl(); // KRename only supports the recursive option combined with a local directory path if (file->isDir() && url.scheme() == "file") { proc << "-r" << url.path(); } else { proc << url.toString(); } } if (!proc.startDetached()) KMessageBox::error(0, i18n("Error executing '%1'.", proc.program().join(" "))); } void KRslots::rootKrusader() { if (KMessageBox::warningContinueCancel( krApp, i18n("Improper operations in root mode can damage your operating system. " "

Furthermore, running UI applications as root is insecure and can " "allow attackers to gain root access."), QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "Confirm Root Mode", KMessageBox::Notify | KMessageBox::Dangerous) != KMessageBox::Continue) return; if (!KrServices::isExecutable(KDESU_PATH)) { KMessageBox::sorry(krApp, i18n("Cannot start root mode Krusader, %1 not found or not executable. " "Please verify that kde-cli-tools are installed.", QString(KDESU_PATH))); return; } KProcess proc; proc << KDESU_PATH << "-c" << QApplication::instance()->applicationFilePath() + " --left=" + KrServices::quote(LEFT_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)) + " --right=" + KrServices::quote(RIGHT_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)); if (!proc.startDetached()) KMessageBox::error(0, i18n("Error executing %1.", proc.program()[0])); } void KRslots::slotSplit() { const QStringList list = ACTIVE_PANEL->gui->getSelectedNames(); QString name; // first, see if we've got exactly 1 selected file, if not, try the current one if (list.count() == 1) name = list[0]; if (name.isEmpty()) { // if we got here, then one of the panel can't be sure what file to diff KMessageBox::error(0, i18n("Do not know which file to split.")); return; } QUrl fileURL = ACTIVE_FUNC->files()->getUrl(name); if (fileURL.isEmpty()) return; if (ACTIVE_FUNC->files()->getFileItem(name)->isDir()) { KMessageBox::sorry(krApp, i18n("You cannot split a folder.")); return; } const QUrl destDir = ACTIVE_PANEL->otherPanel()->virtualPath(); SplitterGUI splitterGUI(MAIN_VIEW, fileURL, destDir); if (splitterGUI.exec() == QDialog::Accepted) { bool splitToOtherPanel = splitterGUI.getDestinationDir().matches(ACTIVE_PANEL->otherPanel()->virtualPath(), QUrl::StripTrailingSlash); Splitter split(MAIN_VIEW, fileURL, splitterGUI.getDestinationDir(), splitterGUI.overWriteFiles()); split.split(splitterGUI.getSplitSize()); if (splitToOtherPanel) ACTIVE_PANEL->otherPanel()->func->refresh(); } } void KRslots::slotCombine() { const QStringList list = ACTIVE_PANEL->gui->getSelectedNames(); if (list.isEmpty()) { KMessageBox::error(0, i18n("Do not know which files to combine.")); return; } QUrl baseURL; bool unixStyle = false; bool windowsStyle = false; QString commonName; int commonLength = 0; /* checking splitter names */ for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) { QUrl url = ACTIVE_FUNC->files()->getUrl(*it); if (url.isEmpty()) return; if (ACTIVE_FUNC->files()->getFileItem(*it)->isDir()) { KMessageBox::sorry(krApp, i18n("You cannot combine a folder.")); return; } if (!unixStyle) { QString name = url.fileName(); int extPos = name.lastIndexOf('.'); QString ext = name.mid(extPos + 1); name.truncate(extPos); url = url.adjusted(QUrl::RemoveFilename); url.setPath(url.path() + name); bool isExtInt; ext.toInt(&isExtInt, 10); if (extPos < 1 || ext.isEmpty() || (ext != "crc" && !isExtInt)) { if (windowsStyle) { KMessageBox::error(0, i18n("Not a split file: %1.", url.toDisplayString(QUrl::PreferLocalFile))); return; } unixStyle = true; } else { if (ext != "crc") windowsStyle = true; if (baseURL.isEmpty()) baseURL = url; else if (baseURL != url) { KMessageBox::error(0, i18n("Select only one split file.")); return; } } } if (unixStyle) { bool error = true; do { QString shortName = *it; QChar lastChar = shortName.at(shortName.length() - 1); if (lastChar.isLetter()) { char fillLetter = (lastChar.toUpper() == lastChar) ? 'A' : 'a'; if (commonName.isNull()) { commonLength = shortName.length(); commonName = shortName; while (commonName.length()) { QString shorter = commonName.left(commonName.length() - 1); QString testFile = shorter.leftJustified(commonLength, fillLetter); if (ACTIVE_FUNC->files()->getFileItem(testFile) == 0) break; else { commonName = shorter; baseURL = ACTIVE_PANEL->virtualPath().adjusted(QUrl::StripTrailingSlash); baseURL.setPath(baseURL.path() + '/' + (testFile)); } } error = (commonName == shortName); } else if (commonLength == shortName.length() && shortName.startsWith(commonName)) error = false; } } while (false); if (error) { KMessageBox::error(0, i18n("Not a split file: %1.", url.toDisplayString(QUrl::PreferLocalFile))); return; } } } // ask the user for the copy dest QUrl dest = KChooseDir::getDir(i18n("Combining %1.* to folder:", baseURL.toDisplayString(QUrl::PreferLocalFile)), ACTIVE_PANEL->otherPanel()->virtualPath(), ACTIVE_PANEL->virtualPath()); if (dest.isEmpty()) return ; // the user canceled bool combineToOtherPanel = (dest.matches(ACTIVE_PANEL->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)); Combiner combine(MAIN_VIEW, baseURL, dest, unixStyle); combine.combine(); if (combineToOtherPanel) ACTIVE_PANEL->otherPanel()->func->refresh(); } void KRslots::manageUseractions() { ActionMan actionMan(MAIN_VIEW); } #ifdef SYNCHRONIZER_ENABLED void KRslots::slotSynchronizeDirs(QStringList selected) { SynchronizerGUI *synchronizerDialog = new SynchronizerGUI(MAIN_VIEW, LEFT_PANEL->virtualPath(), RIGHT_PANEL->virtualPath(), selected); synchronizerDialog->show(); // destroyed on close } #endif void KRslots::compareSetup() { for (int i = 0; KrActions::compareArray[i] != 0; i++) if ((*KrActions::compareArray[i])->isChecked()) { KConfigGroup group(krConfig, "Private"); group.writeEntry("Compare Mode", i); break; } } /** called by actions actExec* to choose the built-in command line mode */ void KRslots::execTypeSetup() { for (int i = 0; KrActions::execTypeArray[i] != 0; i++) if ((*KrActions::execTypeArray[i])->isChecked()) { if (*KrActions::execTypeArray[i] == KrActions::actExecTerminalEmbedded) { // if commands are to be executed in the TE, it must be loaded MAIN_VIEW->terminalDock()->initialise(); } KConfigGroup grp(krConfig, "Private"); grp.writeEntry("Command Execution Mode", i); break; } } void KRslots::slotDiskUsage() { DiskUsageGUI *diskUsageDialog = new DiskUsageGUI(ACTIVE_PANEL->virtualPath()); diskUsageDialog->askDirAndShow(); } void KRslots::applicationStateChanged() { if (MAIN_VIEW == 0) { /* CRASH FIX: it's possible that the method is called after destroying the main view */ return; } if(qApp->applicationState() == Qt::ApplicationActive || qApp->applicationState() == Qt::ApplicationInactive) { LEFT_PANEL->panelVisible(); RIGHT_PANEL->panelVisible(); } else { LEFT_PANEL->panelHidden(); RIGHT_PANEL->panelHidden(); } } void KRslots::emptyTrash() { KrTrashHandler::emptyTrash(); } #define OPEN_ID 100001 #define EMPTY_TRASH_ID 100002 void KRslots::trashPopupMenu() { QMenu trashMenu(krApp); QAction * act = trashMenu.addAction(krLoader->loadIcon("document-open", KIconLoader::Panel), i18n("Open trash bin")); act->setData(QVariant(OPEN_ID)); act = trashMenu.addAction(krLoader->loadIcon("trash-empty", KIconLoader::Panel), i18n("Empty trash bin")); act->setData(QVariant(EMPTY_TRASH_ID)); int result = -1; QAction *res = trashMenu.exec(QCursor::pos()); if (res && res->data().canConvert ()) result = res->data().toInt(); if (result == OPEN_ID) { ACTIVE_FUNC->openUrl(QUrl(QStringLiteral("trash:/"))); } else if (result == EMPTY_TRASH_ID) { KrTrashHandler::emptyTrash(); } } //shows the JavaScript-Console void KRslots::jsConsole() { #ifdef __KJSEMBED__ if (! krJS) krJS = new KrJS(); krJS->view()->show(); #endif } void KRslots::addBookmark() { krBookMan->bookmarkCurrent(ACTIVE_PANEL->virtualPath()); } void KRslots::cmdlinePopup() { MAIN_VIEW->cmdLine()->popup(); } diff --git a/krusader/krslots.h b/krusader/krslots.h index 14c95435..64f5bc4e 100644 --- a/krusader/krslots.h +++ b/krusader/krslots.h @@ -1,126 +1,117 @@ -/*************************************************************************** - krslots.h - ------------------- - copyright : (C) 2001 by Shie Erlich & Rafi Yanai - email : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2001 Shie Erlich * + * Copyright (C) 2001 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRSLOTS_H #define KRSLOTS_H // QtCore #include #include #include #include class KrMainWindow; class QUrl; class KrProcess: public KProcess { Q_OBJECT QString tmp1, tmp2; public: KrProcess(QString in1, QString in2) { tmp1 = in1; tmp2 = in2; connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processHasExited())); } public slots: void processHasExited() { if (!tmp1.isEmpty()) QFile::remove(tmp1); if (!tmp2.isEmpty()) QFile::remove(tmp2); deleteLater(); } }; class KRslots : public QObject { Q_OBJECT public: enum compareMode { full }; explicit KRslots(QObject *parent); ~KRslots() {} public slots: void sendFileByEmail(const QList &filename); void compareContent(); void compareContent(QUrl, QUrl); void insertFileName(bool fullPath); void rootKrusader(); void swapPanels(); void showHiddenFiles(bool show); void toggleSwapSides(); void updateStatusbarVisibility(); void toggleTerminal(); void compareSetup(); void emptyTrash(); void trashPopupMenu(); /** called by actExec* actions to choose the built-in command line mode */ void execTypeSetup(); void refresh(const QUrl &u); void runKonfigurator(bool firstTime = false); void startKonfigurator() { runKonfigurator(false); } void search(); // call the search module void locate(); void runTerminal(const QString & dir); void homeTerminal(); void addBookmark(); void toggleFnkeys(); void toggleCmdline(); void multiRename(); void cmdlinePopup(); void slotSplit(); void slotCombine(); void manageUseractions(); #ifdef SYNCHRONIZER_ENABLED void slotSynchronizeDirs(QStringList selected = QStringList()); #endif void slotDiskUsage(); void applicationStateChanged(); void jsConsole(); protected slots: void configChanged(bool isGUIRestartNeeded); protected: KrMainWindow *_mainWindow; }; #endif diff --git a/krusader/krusader.cpp b/krusader/krusader.cpp index 71297c7b..07160745 100644 --- a/krusader/krusader.cpp +++ b/krusader/krusader.cpp @@ -1,653 +1,644 @@ -/*************************************************************************** - krusader.cpp - ------------------- -copyright : (C) 2000 by Shie Erlich & Rafi Yanai -e-mail : krusader@users.sourceforge.net -web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- -Description -*************************************************************************** - -A - -db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. -88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D -88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' -88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b -88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. -YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krusader.h" // QtCore #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include // QtDBus #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defaults.h" #include "kicons.h" #include "kractions.h" #include "krglobal.h" #include "krservices.h" #include "krslots.h" #include "krtrashhandler.h" #include "krusaderversion.h" #include "krusaderview.h" #include "panelmanager.h" #include "tabactions.h" #include "BookMan/krbookmarkhandler.h" #include "Dialogs/checksumdlg.h" #include "Dialogs/krpleasewait.h" #include "Dialogs/popularurls.h" #include "FileSystem/fileitem.h" #include "FileSystem/krpermhandler.h" #include "GUI/kcmdline.h" #include "GUI/kfnkeys.h" #include "GUI/krremoteencodingmenu.h" #include "GUI/krusaderstatus.h" #include "GUI/terminaldock.h" #include "JobMan/jobman.h" #include "KViewer/krviewer.h" #include "Konfigurator/kgprotocols.h" #include "MountMan/kmountman.h" #include "Panel/PanelView/krview.h" #include "Panel/PanelView/krviewfactory.h" #include "Panel/krcolorcache.h" #include "Panel/krpanel.h" #include "Panel/listpanelactions.h" #include "Panel/viewactions.h" #include "UserAction/expander.h" // This makes gcc-4.1 happy. Warning about possible problem with KrAction's dtor not called #include "UserAction/kraction.h" #include "UserAction/useraction.h" #ifdef __KJSEMBED__ #include "KrJS/krjs.h" #endif // define the static members Krusader *Krusader::App = 0; QString Krusader::AppName; // KrBookmarkHandler *Krusader::bookman = 0; //QTextOStream *Krusader::_krOut = QTextOStream(::stdout); #ifdef __KJSEMBED__ KrJS *Krusader::js = 0; QAction *Krusader::actShowJSConsole = 0; #endif // construct the views, statusbar and menu bars and prepare Krusader to start Krusader::Krusader(const QCommandLineParser &parser) : KParts::MainWindow(0, Qt::Window | Qt::WindowTitleHint | Qt::WindowContextHelpButtonHint), _listPanelActions(0), isStarting(true), isExiting(false), _quit(false) { // create the "krusader" App = this; krMainWindow = this; SLOTS = new KRslots(this); setXMLFile("krusaderui.rc"); // kpart-related xml file plzWait = new KRPleaseWaitHandler(this); const bool runKonfig = versionControl(); QString message; switch (krConfig->accessMode()) { case KConfigBase::NoAccess : message = "Krusader's configuration file can't be found. Default values will be used."; break; case KConfigBase::ReadOnly : message = "Krusader's configuration file is in READ ONLY mode (why is that!?) Changed values will not be saved"; break; case KConfigBase::ReadWrite : message = ""; break; } if (!message.isEmpty()) { KMessageBox::error(krApp, message); } // create an icon loader krLoader = KIconLoader::global(); // iconLoader->addExtraDesktopThemes(); // create MountMan KrGlobal::mountMan = new KMountMan(this); connect(KrGlobal::mountMan, SIGNAL(refreshPanel(QUrl)), SLOTS, SLOT(refresh(QUrl))); // create bookman krBookMan = new KrBookmarkHandler(this); // create job manager krJobMan = new JobMan(this); _popularUrls = new PopularUrls(this); // create the main view MAIN_VIEW = new KrusaderView(this); // setup all the krusader's actions setupActions(); // init the permmision handler class KRpermHandler::init(); // init the protocol handler KgProtocols::init(); const KConfigGroup lookFeelGroup(krConfig, "Look&Feel"); FileItem::loadUserDefinedFolderIcons(lookFeelGroup.readEntry("Load User Defined Folder Icons", _UserDefinedFolderIcons)); const KConfigGroup startupGroup(krConfig, "Startup"); QString startProfile = startupGroup.readEntry("Starter Profile Name", QString()); QList leftTabs; QList rightTabs; // get command-line arguments if (parser.isSet("left")) { leftTabs = KrServices::toUrlList(parser.value("left").split(',')); startProfile.clear(); } if (parser.isSet("right")) { rightTabs = KrServices::toUrlList(parser.value("right").split(',')); startProfile.clear(); } if (parser.isSet("profile")) startProfile = parser.value("profile"); if (!startProfile.isEmpty()) { leftTabs.clear(); rightTabs.clear(); } // starting the panels MAIN_VIEW->start(startupGroup, startProfile.isEmpty(), leftTabs, rightTabs); // create a status bar KrusaderStatus *status = new KrusaderStatus(this); setStatusBar(status); status->setWhatsThis(i18n("Statusbar will show basic information " "about file below mouse pointer.")); // create tray icon (if needed) const bool startToTray = startupGroup.readEntry("Start To Tray", _StartToTray); setTray(startToTray); setCentralWidget(MAIN_VIEW); // manage our keyboard short-cuts //KAcceleratorManager::manage(this,true); setCursor(Qt::ArrowCursor); if (! startProfile.isEmpty()) MAIN_VIEW->profiles(startProfile); // restore gui settings { // now, check if we need to create a konsole_part // call the XML GUI function to draw the UI createGUI(MAIN_VIEW->terminalDock()->part()); // this needs to be called AFTER createGUI() !!! updateUserActions(); _listPanelActions->guiUpdated(); // not using this. See savePosition() //applyMainWindowSettings(); const KConfigGroup cfgToolbar(krConfig, "Main Toolbar"); toolBar()->applySettings(cfgToolbar); const KConfigGroup cfgJobBar(krConfig, "Job Toolbar"); toolBar("jobToolBar")->applySettings(cfgJobBar); const KConfigGroup cfgActionsBar(krConfig, "Actions Toolbar"); toolBar("actionsToolBar")->applySettings(cfgActionsBar); // restore toolbars position and visibility restoreState(startupGroup.readEntry("State", QByteArray())); statusBar()->setVisible(startupGroup.readEntry("Show status bar", _ShowStatusBar)); MAIN_VIEW->updateGUI(startupGroup); // popular urls _popularUrls->load(); } if (runKonfig) SLOTS->runKonfigurator(true); KConfigGroup viewerModuleGrp(krConfig, "ViewerModule"); if (viewerModuleGrp.readEntry("FirstRun", true)) { KrViewer::configureDeps(); viewerModuleGrp.writeEntry("FirstRun", false); } if (!runKonfig) { KConfigGroup cfg(krConfig, "Private"); move(cfg.readEntry("Start Position", _StartPosition)); resize(cfg.readEntry("Start Size", _StartSize)); } // view initialized; show window or only tray if (!startToTray) { show(); } KrTrashHandler::startWatcher(); isStarting = false; //HACK - used by [ListerTextArea|KrSearchDialog|LocateDlg]:keyPressEvent() KrGlobal::copyShortcut = _listPanelActions->actCopy->shortcut(); //HACK: make sure the active view becomes focused // for some reason sometimes the active view cannot be focused immediately at this point, // so queue it for the main loop QTimer::singleShot(0, ACTIVE_PANEL->view->widget(), SLOT(setFocus())); _openUrlTimer.setSingleShot(true); connect(&_openUrlTimer, SIGNAL(timeout()), SLOT(doOpenUrl())); KStartupInfo *startupInfo = new KStartupInfo(0, this); connect(startupInfo, &KStartupInfo::gotNewStartup, this, &Krusader::slotGotNewStartup); connect(startupInfo, &KStartupInfo::gotRemoveStartup, this, &Krusader::slotGotRemoveStartup); } Krusader::~Krusader() { KrTrashHandler::stopWatcher(); if (!isExiting) // save the settings if it was not saved (SIGTERM received) saveSettings(); delete MAIN_VIEW; MAIN_VIEW = 0; App = 0; } void Krusader::setTray(bool forceCreation) { const bool trayIsNeeded = forceCreation || KConfigGroup(krConfig, "Look&Feel") .readEntry("Minimize To Tray", _ShowTrayIcon); if (!sysTray && trayIsNeeded) { sysTray = new KStatusNotifierItem(this); sysTray->setIconByName(privIcon()); // we have our own "quit" method, re-connect QAction *quitAction = sysTray->action(QStringLiteral("quit")); if (quitAction) { disconnect(quitAction, &QAction::triggered, nullptr, nullptr); connect(quitAction, &QAction::triggered, this, &Krusader::quit); } } else if (sysTray && !trayIsNeeded) { // user does not want tray anymore :( sysTray->deleteLater(); } } bool Krusader::versionControl() { // create config file krConfig = KSharedConfig::openConfig().data(); KConfigGroup nogroup(krConfig, QString()); const bool firstRun = nogroup.readEntry("First Time", true); KrGlobal::sCurrentConfigVersion = nogroup.readEntry("Config Version", -1); // first installation of krusader if (firstRun) { KMessageBox::information( krApp, i18n("Welcome to Krusader.

As this is your first run, your machine " "will now be checked for external applications. Then the Konfigurator will " "be launched where you can customize Krusader to your needs.

")); } nogroup.writeEntry("Version", VERSION); nogroup.writeEntry("First Time", false); krConfig->sync(); QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/krusader/")); return firstRun; } void Krusader::statusBarUpdate(const QString& mess) { // change the message on the statusbar for 5 seconds if (statusBar()->isVisible()) statusBar()->showMessage(mess, 5000); } bool Krusader::event(QEvent *e) { if(e->type() == QEvent::ApplicationPaletteChange) { KrColorCache::getColorCache().refreshColors(); } return KParts::MainWindow::event(e); } // Moving from Pixmap actions to generic filenames - thanks to Carsten Pfeiffer void Krusader::setupActions() { QAction *bringToTopAct = new QAction(i18n("Bring Main Window to Top"), this); actionCollection()->addAction("bring_main_window_to_top", bringToTopAct); connect(bringToTopAct, SIGNAL(triggered()), SLOT(moveToTop())); KrActions::setupActions(this); _krActions = new KrActions(this); _viewActions = new ViewActions(this, this); _listPanelActions = new ListPanelActions(this, this); _tabActions = new TabActions(this, this); } /////////////////////////////////////////////////////////////////////////// //////////////////// implementation of slots ////////////////////////////// /////////////////////////////////////////////////////////////////////////// void Krusader::savePosition() { KConfigGroup cfg(krConfig, "Private"); cfg.writeEntry("Start Position", pos()); cfg.writeEntry("Start Size", size()); cfg = krConfig->group("Startup"); MAIN_VIEW->saveSettings(cfg); // NOTE: this would save current window state/size, statusbar and settings for each toolbar. // We are not using this and saving everything manually because // - it does not save window position // - window size save/restore does sometimes not work (multi-monitor setup) // - saving the statusbar visibility should be independent from window position and restoring it // does not work properly. //KConfigGroup cfg = KConfigGroup(&cfg, "MainWindowSettings"); //saveMainWindowSettings(cfg); //statusBar()->setVisible(cfg.readEntry("StatusBar", "Enabled") != "Disabled"); krConfig->sync(); } void Krusader::saveSettings() { // workaround: revert terminal fullscreen mode before saving widget and toolbar visibility if (MAIN_VIEW->isTerminalEmulatorFullscreen()) { MAIN_VIEW->setTerminalEmulator(false, true); } KConfigGroup noGroup(krConfig, QString()); noGroup.writeEntry("Config Version", KrGlobal::sConfigVersion); // save toolbar settings KConfigGroup cfg(krConfig, "Main Toolbar"); toolBar()->saveSettings(cfg); cfg = krConfig->group("Job Toolbar"); toolBar("jobToolBar")->saveSettings(cfg); cfg = krConfig->group("Actions Toolbar"); toolBar("actionsToolBar")->saveSettings(cfg); cfg = krConfig->group("Startup"); // save toolbar visibility and position cfg.writeEntry("State", saveState()); cfg.writeEntry("Show status bar", statusBar()->isVisible()); // save panel and window settings if (cfg.readEntry("Remember Position", _RememberPos)) savePosition(); // save the gui components visibility if (cfg.readEntry("UI Save Settings", _UiSave)) { cfg.writeEntry("Show FN Keys", KrActions::actToggleFnkeys->isChecked()); cfg.writeEntry("Show Cmd Line", KrActions::actToggleCmdline->isChecked()); cfg.writeEntry("Show Terminal Emulator", KrActions::actToggleTerminal->isChecked()); } // save popular links _popularUrls->save(); krConfig->sync(); } void Krusader::closeEvent(QCloseEvent *event) { if (!sysTray || _quit) { _quit = false; // in case quit will be aborted KParts::MainWindow::closeEvent(event); // (may) quit, continues with queryClose()... } else { // close window to tray event->ignore(); hide(); } } void Krusader::showEvent(QShowEvent *event) { const KConfigGroup lookFeelGroup(krConfig, "Look&Feel"); if (sysTray && !lookFeelGroup.readEntry("Minimize To Tray", _ShowTrayIcon)) { // restoring from "start to tray", tray icon is not needed anymore sysTray->deleteLater(); } KParts::MainWindow::showEvent(event); } bool Krusader::queryClose() { if (isStarting || isExiting) return false; if (qApp->isSavingSession()) { // KDE is logging out, accept the close acceptClose(); return true; } const KConfigGroup cfg = krConfig->group("Look&Feel"); const bool confirmExit = cfg.readEntry("Warn On Exit", _WarnOnExit); // ask user and wait until all KIO::job operations are terminated. Krusader won't exit before // that anyway if (!krJobMan->waitForJobs(confirmExit)) return false; /* First try to close the child windows, because it's the safer way to avoid crashes, then close the main window. If closing a child is not successful, then we cannot let the main window close. */ for (;;) { QWidgetList list = QApplication::topLevelWidgets(); QWidget *activeModal = QApplication::activeModalWidget(); QWidget *w = list.at(0); if (activeModal && activeModal != this && activeModal != menuBar() && list.contains(activeModal) && !activeModal->isHidden()) { w = activeModal; } else { int i = 1; for (; i < list.count(); ++i) { w = list.at(i); if (!(w && (w == this || w->isHidden() || w == menuBar()))) break; } if (i == list.count()) w = 0; } if (!w) break; if (!w->close()) { if (w->inherits("QDialog")) { fprintf(stderr, "Failed to close: %s\n", w->metaObject()->className()); } return false; } } acceptClose(); return true; } void Krusader::acceptClose() { saveSettings(); emit shutdown(); // Removes the DBUS registration of the application. Single instance mode requires unique appid. // As Krusader is exiting, we release that unique appid, so new Krusader instances // can be started. QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.unregisterObject("/Instances/" + Krusader::AppName); isExiting = true; } // the please wait dialog functions void Krusader::startWaiting(QString msg, int count , bool cancel) { plzWait->startWaiting(msg , count, cancel); } bool Krusader::wasWaitingCancelled() const { return plzWait->wasCancelled(); } void Krusader::stopWait() { plzWait->stopWait(); } void Krusader::updateUserActions() { KActionMenu *userActionMenu = (KActionMenu *) KrActions::actUserMenu; if (userActionMenu) { userActionMenu->menu()->clear(); userActionMenu->addAction(KrActions::actManageUseractions); userActionMenu->addSeparator(); krUserAction->populateMenu(userActionMenu, NULL); } } const char* Krusader::privIcon() { if (geteuid()) return "krusader_user"; else return "krusader_root"; } void Krusader::quit() { _quit = true; // remember that we want to quit and not close to tray close(); // continues with closeEvent()... } void Krusader::moveToTop() { if (isHidden()) show(); KWindowSystem::forceActiveWindow(winId()); } bool Krusader::isRunning() { moveToTop(); //FIXME - doesn't belong here return true; } bool Krusader::isLeftActive() { return MAIN_VIEW->isLeftActive(); } bool Krusader::openUrl(QString url) { _urlToOpen = url; _openUrlTimer.start(0); return true; } void Krusader::doOpenUrl() { QUrl url = QUrl::fromUserInput(_urlToOpen, QDir::currentPath(), QUrl::AssumeLocalFile); _urlToOpen.clear(); int tab = ACTIVE_MNG->findTab(url); if(tab >= 0) ACTIVE_MNG->setActiveTab(tab); else if((tab = OTHER_MNG->findTab(url)) >= 0) { OTHER_MNG->setActiveTab(tab); OTHER_MNG->currentPanel()->view->widget()->setFocus(); } else ACTIVE_MNG->slotNewTab(url); } void Krusader::slotGotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data) { Q_UNUSED(id) Q_UNUSED(data) // This is here to show busy mouse cursor when _other_ applications are launched, not for krusader itself. qApp->setOverrideCursor(Qt::BusyCursor); } void Krusader::slotGotRemoveStartup(const KStartupInfoId &id, const KStartupInfoData &data) { Q_UNUSED(id) Q_UNUSED(data) qApp->restoreOverrideCursor(); } KrView *Krusader::activeView() { return ACTIVE_PANEL->view; } AbstractPanelManager *Krusader::activeManager() { return MAIN_VIEW->activeManager(); } AbstractPanelManager *Krusader::leftManager() { return MAIN_VIEW->leftManager(); } AbstractPanelManager *Krusader::rightManager() { return MAIN_VIEW->rightManager(); } diff --git a/krusader/krusader.h b/krusader/krusader.h index 8775bf5a..c6e3ea6a 100644 --- a/krusader/krusader.h +++ b/krusader/krusader.h @@ -1,196 +1,186 @@ -/*************************************************************************** - krusader.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - The main application ! what's more to say ? - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #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); virtual ~Krusader(); void setTray(bool forceCreation = false); // KrMainWindow implementation virtual QWidget *widget() Q_DECL_OVERRIDE { return this; } virtual KrView *activeView() Q_DECL_OVERRIDE; ViewActions *viewActions() { return _viewActions; } virtual KActionCollection *actions() { return actionCollection(); } virtual AbstractPanelManager *activeManager() Q_DECL_OVERRIDE; virtual AbstractPanelManager *leftManager() Q_DECL_OVERRIDE; virtual AbstractPanelManager *rightManager() Q_DECL_OVERRIDE; virtual PopularUrls *popularUrls() Q_DECL_OVERRIDE { return _popularUrls; } virtual KrActions *krActions() Q_DECL_OVERRIDE { return _krActions; } virtual ListPanelActions *listPanelActions() Q_DECL_OVERRIDE { return _listPanelActions; } virtual TabActions *tabActions() Q_DECL_OVERRIDE { return _tabActions; } virtual void plugActionList(const char *name, QList &list) Q_DECL_OVERRIDE { KParts::MainWindow::plugActionList(name, list); } /** * This returns a defferent icon if krusader runs with root-privileges * @return a character string with the specitif icon-name */ static const char* privIcon(); 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 setupActions(); bool versionControl(); // handle version differences in krusaderrc bool event(QEvent *) Q_DECL_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; bool isExiting; 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/krusaderview.cpp b/krusader/krusaderview.cpp index da1713f5..edc6a578 100644 --- a/krusader/krusaderview.cpp +++ b/krusader/krusaderview.cpp @@ -1,538 +1,529 @@ -/*************************************************************************** - krusaderview.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net ---------------------------------------------------------------------------- - Description -*************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - -*************************************************************************** -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include "krusaderview.h" // QtCore #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include "krusader.h" #include "kractions.h" #include "krslots.h" #include "defaults.h" #include "Panel/listpanel.h" #include "Panel/panelfunc.h" #include "GUI/kcmdline.h" #include "GUI/kfnkeys.h" #include "GUI/terminaldock.h" #include "panelmanager.h" #include "GUI/profilemanager.h" #include "Dialogs/percentalsplitter.h" #include "krservices.h" KrusaderView::KrusaderView(QWidget *parent) : QWidget(parent), activeMng(0) { } void KrusaderView::start(const KConfigGroup &cfg, bool restoreSettings, const QList &leftTabs, const QList &rightTabs) { //////////////////////////////// // make a 1x1 mainLayout, it will auto-expand: mainLayout = new QGridLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); // vertical splitter vert_splitter = new QSplitter(this); // splits between panels and terminal/cmdline vert_splitter->setOrientation(Qt::Vertical); // horizontal splitter horiz_splitter = new PercentalSplitter(vert_splitter); (_terminalDock = new TerminalDock(vert_splitter, krApp))->hide(); // create it hidden // create a command line thing _cmdLine = new KCMDLine(this); // add a panel manager for each side of the splitter leftMng = createManager(true); rightMng = createManager(false); leftMng->setOtherManager(rightMng); rightMng->setOtherManager(leftMng); // make the left panel focused at program start activeMng = leftMng; // create the function keys widget _fnKeys = new KFnKeys(this, krApp); _fnKeys->hide(); _fnKeys->setWhatsThis(i18n("Function keys allow performing fast " "operations on files.")); // and insert the whole thing into the main layout... at last mainLayout->addWidget(vert_splitter, 0, 0); //<> mainLayout->addWidget(_cmdLine, 1, 0); mainLayout->addWidget(_fnKeys, 2, 0); mainLayout->activate(); // get the last saved sizes of the splitter QList lst = cfg.readEntry("Splitter Sizes", QList()); if (lst.count() != 2) { lst.clear(); lst.push_back(100); lst.push_back(100); } else if (lst[0] < 1 && lst[1] < 1) { lst[ 0 ] = 100; lst[ 1 ] = 100; } horiz_splitter->setSizes(lst); verticalSplitterSizes = cfg.readEntry("Terminal Emulator Splitter Sizes", QList ()); if (verticalSplitterSizes.count() != 2 || (verticalSplitterSizes[0] < 1 && verticalSplitterSizes[1] < 1)) { verticalSplitterSizes.clear(); verticalSplitterSizes << 100 << 100; } leftPanel()->start(leftTabs.isEmpty() ? QUrl::fromLocalFile(QDir::homePath()) : leftTabs.at(0)); rightPanel()->start(rightTabs.isEmpty() ? QUrl::fromLocalFile(QDir::homePath()) : rightTabs.at(0)); activePanel()->gui->slotFocusOnMe(); // left starts out active for (int i = 1; i < leftTabs.count(); i++) leftMng->slotNewTab(leftTabs.at(i), false); for (int j = 1; j < rightTabs.count(); j++) rightMng->slotNewTab(rightTabs.at(j), false); // this is needed so that all tab labels get updated leftMng->layoutTabs(); rightMng->layoutTabs(); if(restoreSettings) { if(leftTabs.isEmpty()) leftMng->loadSettings(KConfigGroup(&cfg, "Left Tab Bar")); if(rightTabs.isEmpty()) rightMng->loadSettings(KConfigGroup(&cfg, "Right Tab Bar")); if (cfg.readEntry("Left Side Is Active", false)) leftPanel()->slotFocusOnMe(); else rightPanel()->slotFocusOnMe(); } } void KrusaderView::updateGUI(const KConfigGroup &cfg) { if (!cfg.readEntry("Show Cmd Line", _ShowCmdline)) { cmdLine()->hide(); KrActions::actToggleCmdline->setChecked(false); } else { cmdLine()->show(); KrActions::actToggleCmdline->setChecked(true); } // update the Fn bar to the shortcuts selected by the user fnKeys()->updateShortcuts(); if (!cfg.readEntry("Show FN Keys", _ShowFNkeys)) { fnKeys()->hide(); KrActions::actToggleFnkeys->setChecked(false); } else { fnKeys()->show(); KrActions::actToggleFnkeys->setChecked(true); } // set vertical mode if (cfg.readEntry("Vertical Mode", false)) { toggleVerticalMode(); } if (cfg.readEntry("Show Terminal Emulator", _ShowTerminalEmulator)) { setTerminalEmulator(true); // create konsole_part }; } void KrusaderView::setPanelSize(bool leftPanel, int percent) { QList panelSizes = horiz_splitter->sizes(); int totalSize = panelSizes[0] + panelSizes[1]; if (leftPanel) { panelSizes[0] = totalSize * percent / 100; panelSizes[1] = totalSize * (100 - percent) / 100; } else { // == RIGHT_PANEL panelSizes[0] = totalSize * (100 - percent) / 100; panelSizes[1] = totalSize * percent / 100; } horiz_splitter->setSizes(panelSizes); } PanelManager *KrusaderView::createManager(bool left) { PanelManager *panelManager = new PanelManager(horiz_splitter, krApp, left); connect(panelManager, &PanelManager::draggingTab, this, &KrusaderView::draggingTab); connect(panelManager, &PanelManager::draggingTabFinished, this, &KrusaderView::draggingTabFinished); connect(panelManager, &PanelManager::pathChanged, this, &KrusaderView::slotPathChanged); connect(panelManager, &PanelManager::setActiveManager, this, &KrusaderView::slotSetActiveManager); return panelManager; } void KrusaderView::updateCurrentActivePath() { const QString path = activePanel()->gui->lastLocalPath(); _cmdLine->setCurrent(path); KConfigGroup cfg = krConfig->group("General"); if (_terminalDock->isInitialised() && cfg.readEntry("Send CDs", _SendCDs)) { _terminalDock->sendCd(path); } } KrPanel *KrusaderView::activePanel() const { // active manager might not be set yet return activeMng ? activeMng->currentPanel() : nullptr; } ListPanel *KrusaderView::leftPanel() const { return leftMng->currentPanel()->gui; } ListPanel *KrusaderView::rightPanel() const { return rightMng->currentPanel()->gui; } // updates the command line whenever current panel or its path changes void KrusaderView::slotPathChanged(ListPanel *listPanel) { if (listPanel == activePanel()) { updateCurrentActivePath(); } } int KrusaderView::getFocusCandidates(QVector &widgets) { activePanel()->gui->getFocusCandidates(widgets); if(_terminalDock->isTerminalVisible()) widgets << _terminalDock; if(_cmdLine->isVisible()) widgets << _cmdLine; for(int i = 0; i < widgets.count(); i++) { if(widgets[i] == focusWidget() || widgets[i]->focusWidget() == focusWidget()) return i; } return -1; } void KrusaderView::focusUp() { qDebug() << "focus UP"; QVector widgets; int currentFocus = getFocusCandidates(widgets); if(currentFocus < 0) return; currentFocus--; if(currentFocus >= 0 && currentFocus < widgets.count()) widgets[currentFocus]->setFocus(); } void KrusaderView::focusDown() { qDebug() << "focus DOWN"; QVector widgets; int currentFocus = getFocusCandidates(widgets); if(currentFocus < 0) return; currentFocus++; if(currentFocus < widgets.count()) widgets[currentFocus]->setFocus(); } void KrusaderView::cmdLineFocus() // command line receive's keyboard focus { _cmdLine->setFocus(); } void KrusaderView::cmdLineUnFocus() // return focus to the active panel { activePanel()->gui->slotFocusOnMe(); } // Tab - switch focus void KrusaderView::panelSwitch() { activePanel()->otherPanel()->gui->slotFocusOnMe(); } void KrusaderView::slotSetActiveManager(PanelManager *manager) { activeMng = manager; updateCurrentActivePath(); } void KrusaderView::swapSides() { QList lst = horiz_splitter->sizes(); horiz_splitter->addWidget(leftMng); int old = lst[ 0 ]; lst[ 0 ] = lst [ 1 ]; lst[ 1 ] = old; horiz_splitter->setSizes(lst); PanelManager *tmpMng = leftMng; leftMng = rightMng; rightMng = tmpMng; leftMng->setLeft(true); rightMng->setLeft(false); leftPanel()->updateGeometry(); rightPanel()->updateGeometry(); } void KrusaderView::setTerminalEmulator(bool show, bool fullscreen) { qDebug() << "show=" << show << " fullscreen=" << fullscreen; static bool fnKeysShown = true; // first time init. should be overridden static bool cmdLineShown = true; static bool statusBarShown = true; static bool mainToolBarShown = true; static bool jobToolBarShown = true; static bool actionToolBarShown = true; static bool menuBarShown = true; static bool terminalEmulatorShown = true; if (show) { if (fullscreen) { // save what is shown fnKeysShown = !_fnKeys->isHidden(); cmdLineShown = !_cmdLine->isHidden(); statusBarShown = !krApp->statusBar()->isHidden(); mainToolBarShown = !krApp->toolBar()->isHidden(); jobToolBarShown = !krApp->toolBar("jobToolBar")->isHidden(); actionToolBarShown = !krApp->toolBar("actionToolBar")->isHidden(); menuBarShown = !krApp->menuBar()->isHidden(); terminalEmulatorShown = _terminalDock->isTerminalVisible(); } if(!_terminalDock->isTerminalVisible()) { // show terminal const bool isInitialized = _terminalDock->initialise(); if (!isInitialized) { _terminalDock->hide(); KrActions::actToggleTerminal->setChecked(false); return; } _terminalDock->show(); _terminalDock->setFocus(); updateCurrentActivePath(); KrActions::actToggleTerminal->setChecked(true); } else if (fullscreen) { // save current terminal size before going to fullscreen verticalSplitterSizes = vert_splitter->sizes(); } if (fullscreen) { // hide everything else leftMng->hide(); rightMng->hide(); _fnKeys->hide(); _cmdLine->hide(); krApp->statusBar()->hide(); krApp->toolBar()->hide(); krApp->toolBar("jobToolBar")->hide(); krApp->toolBar("actionToolBar")->hide(); krApp->menuBar()->hide(); // fix showing nothing if terminal is open but splitter widget size is zero vert_splitter->setSizes(QList() << 0 << vert_splitter->height()); } else { vert_splitter->setSizes(verticalSplitterSizes); } } else { // hide const bool isFullscreen = isTerminalEmulatorFullscreen(); if (!(fullscreen && terminalEmulatorShown)) { // hide terminal emulator activePanel()->gui->slotFocusOnMe(); if (_terminalDock->isTerminalVisible() && !isFullscreen) { verticalSplitterSizes = vert_splitter->sizes(); } _terminalDock->hide(); KrActions::actToggleTerminal->setChecked(false); } else { // not fullscreen anymore but terminal is still visible vert_splitter->setSizes(verticalSplitterSizes); } if (isFullscreen) { // restore: unhide everything that was hidden before leftMng->show(); rightMng->show(); if (fnKeysShown) _fnKeys->show(); if (cmdLineShown) _cmdLine->show(); if (statusBarShown) krApp->statusBar()->show(); if (mainToolBarShown) krApp->toolBar()->show(); if (jobToolBarShown) krApp->toolBar("jobToolBar")->show(); if (actionToolBarShown) krApp->toolBar("actionToolBar")->show(); if (menuBarShown) krApp->menuBar()->show(); } } } void KrusaderView::focusTerminalEmulator() { if (_terminalDock->isTerminalVisible()) _terminalDock->setFocus(); } void KrusaderView::toggleFullScreenTerminalEmulator() { setTerminalEmulator(!isTerminalEmulatorFullscreen(), true); } bool KrusaderView::isTerminalEmulatorFullscreen() { return leftMng->isHidden() && rightMng->isHidden(); } void KrusaderView::profiles(QString profileName) { ProfileManager profileManager("Panel", this); profileManager.hide(); connect(&profileManager, SIGNAL(saveToProfile(QString)), this, SLOT(savePanelProfiles(QString))); connect(&profileManager, SIGNAL(loadFromProfile(QString)), this, SLOT(loadPanelProfiles(QString))); if (profileName.isEmpty()) profileManager.profilePopup(); else profileManager.loadProfile(profileName); } void KrusaderView::loadPanelProfiles(QString group) { KConfigGroup ldg(krConfig, group); leftMng->loadSettings(KConfigGroup(&ldg, "Left Tabs")); rightMng->loadSettings(KConfigGroup(&ldg, "Right Tabs")); if (ldg.readEntry("Left Side Is Active", true)) leftPanel()->slotFocusOnMe(); else rightPanel()->slotFocusOnMe(); } void KrusaderView::savePanelProfiles(QString group) { KConfigGroup svr(krConfig, group); svr.writeEntry("Vertical Mode", isVertical()); svr.writeEntry("Left Side Is Active", activePanel()->gui->isLeft()); leftMng->saveSettings(KConfigGroup(&svr, "Left Tabs"), false); rightMng->saveSettings(KConfigGroup(&svr, "Right Tabs"), false); } void KrusaderView::toggleVerticalMode() { if (horiz_splitter->orientation() == Qt::Vertical) { horiz_splitter->setOrientation(Qt::Horizontal); KrActions::actVerticalMode->setText(i18n("Vertical Mode")); KrActions::actVerticalMode->setIcon(QIcon::fromTheme("view-split-top-bottom")); } else { horiz_splitter->setOrientation(Qt::Vertical); KrActions::actVerticalMode->setText(i18n("Horizontal Mode")); KrActions::actVerticalMode->setIcon(QIcon::fromTheme("view-split-left-right")); } } void KrusaderView::saveSettings(KConfigGroup &cfg) { QList lst = horiz_splitter->sizes(); cfg.writeEntry("Splitter Sizes", lst); QList vertSplitterSizes = _terminalDock->isVisible() && !isTerminalEmulatorFullscreen() // fix sizes() not returning correct values on fullscreen+shutdown && vert_splitter->sizes().first() != 0 ? vert_splitter->sizes() : verticalSplitterSizes; cfg.writeEntry("Terminal Emulator Splitter Sizes", vertSplitterSizes); cfg.writeEntry("Vertical Mode", isVertical()); cfg.writeEntry("Left Side Is Active", activePanel()->gui->isLeft()); leftMng->saveSettings(KConfigGroup(&cfg, "Left Tab Bar"), true); rightMng->saveSettings(KConfigGroup(&cfg, "Right Tab Bar"), true); } bool KrusaderView::cursorIsOnOtherSide(PanelManager *of, const QPoint &globalPos) { int border = -1; int pos = -1; if (horiz_splitter->orientation() == Qt::Horizontal) { pos = globalPos.x(); if(of == leftMng) border = leftMng->mapToGlobal(QPoint(leftMng->width(), 0)).x(); else border = rightMng->mapToGlobal(QPoint(0, 0)).x(); } else { pos = globalPos.y(); if(of == leftMng) border = leftMng->mapToGlobal(QPoint(0, leftMng->height())).y(); else border = rightMng->mapToGlobal(QPoint(0, 0)).y(); } return (of == leftMng) ? pos > border : pos < border; } void KrusaderView::draggingTab(PanelManager *from, QMouseEvent *e) { QString icon; if (horiz_splitter->orientation() == Qt::Horizontal) icon = (from == leftMng) ? "arrow-right" : "arrow-left"; else icon = (from == leftMng) ? "arrow-down" : "arrow-up"; QCursor cursor(QIcon::fromTheme(icon).pixmap(22)); if (cursorIsOnOtherSide(from, e->globalPos())) { if(!qApp->overrideCursor()) qApp->setOverrideCursor(cursor); } else qApp->restoreOverrideCursor(); } void KrusaderView::draggingTabFinished(PanelManager *from, QMouseEvent *e) { qApp->restoreOverrideCursor(); if (cursorIsOnOtherSide(from, e->globalPos())) from->moveTabToOtherSide(); } diff --git a/krusader/krusaderview.h b/krusader/krusaderview.h index 39b986db..dc231a10 100644 --- a/krusader/krusaderview.h +++ b/krusader/krusaderview.h @@ -1,122 +1,112 @@ -/*************************************************************************** - krusaderview.h - ------------------- - begin : Thu May 4 2000 - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #ifndef KRUSADERVIEW_H #define KRUSADERVIEW_H // QtCore #include // QtWidgets #include #include #include #include #include #include "krglobal.h" class PanelManager; class ListPanel; class KFnKeys; class KCMDLine; class TerminalDock; class KrusaderView : public QWidget { Q_OBJECT public: explicit KrusaderView(QWidget *parent = 0); virtual ~KrusaderView() {} void start(const KConfigGroup &cfg, bool restoreSettings, const QList &leftTabs, const QList &rightTabs); void updateGUI(const KConfigGroup &cfg); void saveSettings(KConfigGroup &cfg); void cmdLineFocus(); // command line receive's keyboard focus void cmdLineUnFocus();// return focus from command line to active panel bool isLeftActive() const { return leftMng == activeMng; } // used by krGlobal macros PanelManager *activeManager() const { return activeMng; } PanelManager *inactiveManager() const { return activeMng == leftMng ? rightMng : leftMng; } PanelManager *leftManager() const { return leftMng; } PanelManager *rightManager() const { return rightMng; } KrPanel *activePanel() const; ListPanel *leftPanel() const; ListPanel *rightPanel() const; KFnKeys *fnKeys() const { return _fnKeys; } KCMDLine *cmdLine() const { return _cmdLine; } TerminalDock *terminalDock() const { return _terminalDock; } bool isVertical() const { return horiz_splitter != 0 ? horiz_splitter->orientation() == Qt::Vertical : false; } void swapSides(); void setPanelSize(bool leftPanel, int percent); bool isTerminalEmulatorFullscreen(); public slots: void slotSetActiveManager(PanelManager *manager); void slotPathChanged(ListPanel *listPanel); // Tab - switch focus void panelSwitch(); void toggleVerticalMode(); void setTerminalEmulator(bool show, bool fullscreen = false); void focusTerminalEmulator(); void toggleFullScreenTerminalEmulator(); void focusUp(); void focusDown(); void profiles(QString profileName = QString()); void loadPanelProfiles(QString group); void savePanelProfiles(QString group); void draggingTab(PanelManager *from, QMouseEvent *e); void draggingTabFinished(PanelManager *from, QMouseEvent *e); private: int getFocusCandidates(QVector &widgets); bool cursorIsOnOtherSide(PanelManager *of, const QPoint &globalPos); PanelManager *createManager(bool left); void updateCurrentActivePath(); KFnKeys *_fnKeys; // function keys KCMDLine *_cmdLine; // command line widget TerminalDock *_terminalDock; // docking widget for terminal emulator QSplitter *horiz_splitter, *vert_splitter; QList verticalSplitterSizes; PanelManager *activeMng, *leftMng, *rightMng; // saving them for panel swaps QGridLayout *mainLayout, *terminal_layout; }; #endif diff --git a/krusader/main.cpp b/krusader/main.cpp index f85e1856..61fa4345 100644 --- a/krusader/main.cpp +++ b/krusader/main.cpp @@ -1,351 +1,342 @@ -/*************************************************************************** - main.cpp - ------------------- - copyright : (C) 2000 by Shie Erlich & Rafi Yanai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2000 Shie Erlich * + * Copyright (C) 2000 Rafi Yanai * + * Copyright (C) 2004-2018 Krusader Krew [https://krusader.org] * + * * + * This file is part of Krusader [https://krusader.org]. * + * * + * Krusader is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Krusader is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Krusader. If not, see [http://www.gnu.org/licenses/]. * + *****************************************************************************/ #include #include // QtCore #include #include #include #include #include #include #include // QtGui #include // QtDBus #include #include // QtWidgets #include #include #include #include #include #include #include #include "../Archive/krarchandler.h" #include "defaults.h" #include "krservices.h" #include "krslots.h" #include "krusader.h" #include "krusaderversion.h" #include "krusaderview.h" #include "panelmanager.h" static const char *description = I18N_NOOP("Krusader\nTwin-Panel File Manager by KDE"); static void sigterm_handler(int i) { fprintf(stderr, "Signal: %d\n", i); QAbstractEventDispatcher *instance = QAbstractEventDispatcher::instance(); if (instance) instance->wakeUp(); QApplication::exit(- 15); } void openTabsRemote(QStringList tabs, bool left, QString appName) { // make sure left or right are not relative paths for (int i = 0; i != tabs.count(); i++) { tabs[ i ] = tabs[ i ].trimmed(); if (!tabs[ i ].startsWith('/') && tabs[ i ].indexOf(":/") < 0) tabs[ i ] = QDir::currentPath() + '/' + tabs[ i ]; } QDBusInterface remoteApp("org.krusader", "/Instances/" + appName + (left ? "/left_manager" : "/right_manager"), "org.krusader.PanelManager", QDBusConnection::sessionBus()); QDBusReply reply; if (remoteApp.isValid()) reply = remoteApp.call("newTabs", tabs); if (!reply.isValid()) fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); } //! An object that manages archives in several parts of the source code. KRarcHandler arcHandler; int main(int argc, char *argv[]) { // ============ begin icon-stuff =========== // If the user has no icon specified over the commandline we set up our own. // this is according to the users privileges. The icons are in Krusader::privIcon() /* bool hasIcon = false; int i = 0; char * myArgv[argc+2];*/ // if no --miniicon is given, --icon is used. So we don't need to check for --miniicon separately /* for (i = 0; i < argc; ++i) { if (strstr(argv[ i ], "-icon") != 0) // important: just one dash because both can appear! hasIcon = true; } static const char* const icon_text = "--icon"; const char* icon_name = Krusader::privIcon(); char addedParams[strlen(icon_text)+strlen(icon_name)+2]; if (! hasIcon) { for (i = 0; i < argc; ++i) myArgv[ i ] = argv[ i ]; strcpy(addedParams, icon_text); strcpy(addedParams + strlen(icon_text) + 1, icon_name); myArgv[ argc ] = addedParams; myArgv[ ++argc ] = addedParams + strlen(icon_text) + 1; myArgv[ ++argc ] = 0; argv = myArgv; }*/ // ============ end icon-stuff =========== // set global log message format qSetMessagePattern(KrServices::GLOBAL_MESSAGE_PATTERN); // prevent qt5-webengine crashing QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); // create the application and set application domain so that calls to i18n get strings from right place. QApplication app(argc, argv); KLocalizedString::setApplicationDomain("krusader"); // ABOUT data information #ifdef RELEASE_NAME QString versionName = QString("%1 \"%2\"").arg(VERSION).arg(RELEASE_NAME); #else QString versionName = VERSION; #endif KAboutData aboutData(QStringLiteral("krusader"), (geteuid() ? i18n("Krusader") : i18n("Krusader - ROOT PRIVILEGES")), versionName, i18n(description), KAboutLicense::GPL_V2, i18n("(c) 2000-2003, Shie Erlich, Rafi Yanai\n(c) 2004-2016, Krusader Krew"), i18n("Feedback:\nhttps://forum.kde.org/viewforum.php?f=225\n\nIRC\nserver: " "irc.freenode.net, channel: #krusader"), QStringLiteral("https://krusader.org")); aboutData.setOrganizationDomain(QByteArray("kde.org")); aboutData.setDesktopFileName(QStringLiteral("org.kde.krusader")); aboutData.addAuthor(i18n("Rafi Yanai"), i18n("Author (retired)"), QStringLiteral("yanai@users.sourceforge.net")); aboutData.addAuthor(i18n("Shie Erlich"), i18n("Author (retired)"), QStringLiteral("erlich@users.sourceforge.net")); aboutData.addAuthor(i18n("Jan Lepper"), i18n("Developer"), QStringLiteral("jan_lepper@gmx.de"), 0); aboutData.addAuthor(i18n("Andrey Matveyakin"), i18n("Developer"), QStringLiteral("a.matveyakin@gmail.com"), 0); aboutData.addAuthor(i18n("Simon Persson"), i18n("Developer"), QStringLiteral("simon.persson@mykolab.com"), 0); aboutData.addAuthor(i18n("Davide Gianforte"), i18n("Developer"), QStringLiteral("davide@gengisdave.org"), 0); aboutData.addAuthor(i18n("Toni Asensi Esteve"), i18n("Developer"), QStringLiteral("toni.asensi@kdemail.net"), 0); aboutData.addAuthor(i18n("Alexander Bikadorov"), i18n("Developer"), QStringLiteral("alex.bikadorov@kdemail.net"), 0); aboutData.addAuthor(i18n("Karai Csaba"), i18n("Developer (retired)"), QStringLiteral("ckarai@users.sourceforge.net"), 0); aboutData.addAuthor(i18n("Heiner Eichmann"), i18n("Developer (retired)"), QStringLiteral("h.eichmann@gmx.de"), 0); aboutData.addAuthor(i18n("Jonas Bähr"), i18n("Developer (retired)"), QStringLiteral("jonas.baehr@web.de"), 0); aboutData.addAuthor(i18n("Václav Jůza"), i18n("Developer (retired)"), QStringLiteral("vaclavjuza@gmail.com"), 0); aboutData.addAuthor(i18n("Dirk Eschler"), i18n("Webmaster (retired)"), QStringLiteral("deschler@users.sourceforge.net"), 0); aboutData.addAuthor(i18n("Frank Schoolmeesters"), i18n("Documentation and marketing coordinator (retired)"), QStringLiteral("frank_schoolmeesters@yahoo.com"), 0); aboutData.addAuthor(i18n("Richard Holt"), i18n("Documentation & Proofing (retired)"), QStringLiteral("richard.holt@gmail.com"), 0); aboutData.addAuthor(i18n("Matej Urbancic"), i18n("Marketing & Product Research (retired)"), QStringLiteral("matej.urban@gmail.com"), 0); aboutData.addCredit(i18n("kde.org"), i18n("Everyone involved in KDE"), 0, 0); aboutData.addCredit(i18n("l10n.kde.org"), i18n("KDE Translation Teams"), 0, 0); aboutData.addCredit(i18n("Jiří Paleček"), i18n("QA, bug-hunting, patches and general help"), QStringLiteral("jpalecek@web.de"), 0); aboutData.addCredit(i18n("Jiří Klement"), i18n("Important help in KDE 4 porting"), 0, 0); aboutData.addCredit(i18n("Andrew Neupokoev"), i18n("Killer Logo and Icons for Krusader (contest winner)"), QStringLiteral("doom-blue@yandex.ru"), 0); aboutData.addCredit(i18n("The UsefulArts Organization"), i18n("Icon for Krusader"), QStringLiteral("mail@usefularts.org"), 0); aboutData.addCredit(i18n("Gábor Lehel"), i18n("Viewer module for 3rd Hand"), QStringLiteral("illissius@gmail.com"), 0); aboutData.addCredit(i18n("Mark Eatough"), i18n("Handbook Proof-Reader"), QStringLiteral("markeatough@yahoo.com"), 0); aboutData.addCredit(i18n("Jan Halasa"), i18n("The old Bookmark Module"), QStringLiteral("xhalasa@fi.muni.cz"), 0); aboutData.addCredit(i18n("Hans Löffler"), i18n("Dir history button"), 0, 0); aboutData.addCredit(i18n("Szombathelyi György"), i18n("ISO KIO slave"), 0, 0); aboutData.addCredit(i18n("Jan Willem van de Meent (Adios)"), i18n("Icons for Krusader"), QStringLiteral("janwillem@lorentz.leidenuniv.nl"), 0); aboutData.addCredit(i18n("Mikolaj Machowski"), i18n("Usability and QA"), QStringLiteral(""), 0); aboutData.addCredit(i18n("Cristi Dumitrescu"), i18n("QA, bug-hunting, patches and general help"), QStringLiteral("cristid@chip.ro"), 0); aboutData.addCredit(i18n("Aurelien Gateau"), i18n("patch for KViewer"), QStringLiteral("aurelien.gateau@free.fr"), 0); aboutData.addCredit(i18n("Milan Brabec"), i18n("the first patch ever!"), QStringLiteral("mbrabec@volny.cz"), 0); aboutData.addCredit(i18n("Asim Husanovic"), i18n("Bosnian translation"), QStringLiteral("asim@megatel.ba"), 0); aboutData.addCredit(i18n("Doutor Zero"), i18n("Brazilian Portuguese translation"), QStringLiteral("doutor.zero@gmail.com"), 0); aboutData.addCredit(i18n("Milen Ivanov"), i18n("Bulgarian translation"), QStringLiteral("milen.ivanov@abv.bg"), 0); aboutData.addCredit(i18n("Quim Perez"), i18n("Catalan translation"), QStringLiteral("noguer@osona.com"), 0); aboutData.addCredit(i18n("Jinghua Luo"), i18n("Chinese Simplified translation"), QStringLiteral("luojinghua@msn.com"), 0); aboutData.addCredit(i18n("Mitek"), i18n("Old Czech translation"), QStringLiteral("mitek@email.cz"), 0); aboutData.addCredit(i18n("Martin Sixta"), i18n("Old Czech translation"), QStringLiteral("lukumo84@seznam.cz"), 0); aboutData.addCredit(i18n("Vaclav Jůza"), i18n("Czech translation"), QStringLiteral("VaclavJuza@gmail.com"), 0); aboutData.addCredit(i18n("Anders Bruun Olsen"), i18n("Old Danish translation"), QStringLiteral("anders@bruun-olsen.net"), 0); aboutData.addCredit(i18n("Peter H. Sorensen"), i18n("Danish translation"), QStringLiteral("peters@skydebanen.net"), 0); aboutData.addCredit(i18n("Frank Schoolmeesters"), i18n("Dutch translation"), QStringLiteral("frank_schoolmeesters@yahoo.com"), 0); aboutData.addCredit(i18n("Rene-Pierre Lehmann"), i18n("Old French translation"), QStringLiteral("ripi@lepi.org"), 0); aboutData.addCredit(i18n("David Guillerm"), i18n("French translation"), QStringLiteral("dguillerm@gmail.com"), 0); aboutData.addCredit(i18n("Christoph Thielecke"), i18n("Old German translation"), QStringLiteral("crissi99@gmx.de"), 0); aboutData.addCredit(i18n("Dirk Eschler"), i18n("German translation"), QStringLiteral("deschler@users.sourceforge.net"), 0); aboutData.addCredit(i18n("Spiros Georgaras"), i18n("Greek translation"), QStringLiteral("sngeorgaras@gmail.com"), 0); aboutData.addCredit(i18n("Kukk Zoltan"), i18n("Old Hungarian translation"), QStringLiteral("kukkzoli@freemail.hu"), 0); aboutData.addCredit(i18n("Arpad Biro"), i18n("Hungarian translation"), QStringLiteral("biro_arpad@yahoo.com"), 0); aboutData.addCredit(i18n("Giuseppe Bordoni"), i18n("Italian translation"), QStringLiteral("geppo@geppozone.com"), 0); aboutData.addCredit(i18n("Hideki Kimura"), i18n("Japanese translation"), QStringLiteral("hangyo1973@gmail.com"), 0); aboutData.addCredit(i18n("UTUMI Hirosi"), i18n("Old Japanese translation"), QStringLiteral("utuhiro@mx12.freecom.ne.jp"), 0); aboutData.addCredit(i18n("Dovydas Sankauskas"), i18n("Lithuanian translation"), QStringLiteral("laisve@gmail.com"), 0); aboutData.addCredit(i18n("Bruno Queiros"), i18n("Portuguese translation"), QStringLiteral("brunoqueiros@portugalmail.com"), 0); aboutData.addCredit(i18n("Lukasz Janyst"), i18n("Old Polish translation"), QStringLiteral("ljan@wp.pl"), 0); aboutData.addCredit(i18n("Pawel Salawa"), i18n("Polish translation"), QStringLiteral("boogie@myslenice.one.pl"), 0); aboutData.addCredit(i18n("Tomek Grzejszczyk"), i18n("Polish translation"), QStringLiteral("tgrzej@onet.eu"), 0); aboutData.addCredit(i18n("Dmitry A. Bugay"), i18n("Russian translation"), QStringLiteral("sam@vhnet.ru"), 0); aboutData.addCredit(i18n("Dmitry Chernyak"), i18n("Old Russian translation"), QStringLiteral("chernyak@mail.ru"), 0); aboutData.addCredit(i18n("Sasa Tomic"), i18n("Serbian translation"), QStringLiteral("stomic@gmx.net"), 0); aboutData.addCredit(i18n("Zdenko Podobný and Ondrej Pačay (Yogi)"), i18n("Slovak translation"), QStringLiteral("zdenop@gmail.com"), 0); aboutData.addCredit(i18n("Matej Urbancic"), i18n("Slovenian translation"), QStringLiteral("matej.urban@gmail.com"), 0); aboutData.addCredit(i18n("Rafael Munoz"), i18n("Old Spanish translation"), QStringLiteral("muror@hotpop.com"), 0); aboutData.addCredit(i18n("Alejandro Araiza Alvarado"), i18n("Spanish translation"), QStringLiteral("mebrelith@gmail.com"), 0); aboutData.addCredit(i18n("Erik Johanssen"), i18n("Old Swedish translation"), QStringLiteral("erre@telia.com"), 0); aboutData.addCredit(i18n("Anders Linden"), i18n("Old Swedish translation"), QStringLiteral("connyosis@gmx.net"), 0); aboutData.addCredit(i18n("Peter Landgren"), i18n("Swedish translation"), QStringLiteral("peter.talken@telia.com"), 0); aboutData.addCredit(i18n("Bekir Sonat"), i18n("Turkish translation"), QStringLiteral("bekirsonat@kde.org.tr"), 0); aboutData.addCredit(i18n("Ivan Petrouchtchak"), i18n("Ukrainian translation"), QStringLiteral("connyosis@gmx.net"), 0); aboutData.addCredit(i18n("Seongnam Jee"), i18n("Korean translation"), QStringLiteral("snjee@intellicam.com"), 0); // This will call QCoreApplication::setApplicationName, etc for us by using info in the KAboutData instance. // The only thing not called for us is setWindowIcon(), which is why we do it ourselves here. KAboutData::setApplicationData(aboutData); app.setWindowIcon(QIcon::fromTheme(Krusader::privIcon())); // Command line arguments ... QCommandLineParser parser; aboutData.setupCommandLine(&parser); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("left"), i18n("Start left panel at "), QLatin1String("path"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("right"), i18n("Start right panel at "), QLatin1String("path"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("profile"), i18n("Load this profile on startup"), QLatin1String("panel-profile"))); parser.addOption(QCommandLineOption(QStringList() << "d" << QLatin1String("debug"), i18n("Enable debug output"))); parser.addPositionalArgument(QLatin1String("url"), i18n("URL to open")); // check for command line arguments parser.process(app); aboutData.processCommandLine(&parser); // set global message handler KrServices::setGlobalKrMessageHandler(parser.isSet("debug")); KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Look&Feel")); bool singleInstanceMode = cfg.readEntry("Single Instance Mode", _SingleInstanceMode); QString url; if(!parser.positionalArguments().isEmpty()) { url = parser.positionalArguments().first(); } QString appName = "krusader"; if (!singleInstanceMode) appName += QString("%1").arg(getpid()); if (!QDBusConnection::sessionBus().isConnected()) { fprintf(stderr, "Cannot connect to the D-BUS session bus.\n" "To start it, run:\n" "\teval `dbus-launch --auto-syntax`\n"); } if (singleInstanceMode) { QDBusInterface remoteApp("org.krusader", "/Instances/" + appName, "org.krusader.Instance", QDBusConnection::sessionBus()); QDBusReply reply; if (remoteApp.isValid()) reply = remoteApp.call("isRunning"); if (!reply.isValid() && reply.error().type() != QDBusError::ServiceUnknown && reply.error().type() != QDBusError::UnknownObject) fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); if (reply.isValid() && (bool)reply) { KStartupInfo::appStarted(); if (parser.isSet("left")) openTabsRemote(parser.value("left").split(','), true, appName); if (parser.isSet("right")) openTabsRemote(parser.value("right").split(','), false, appName); if(!url.isEmpty()) { reply = remoteApp.call("openUrl", url); if (!reply.isValid()) fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); } return 0; } } // splash screen - if the user wants one QSplashScreen *splash = 0; { // don't remove bracket KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Look&Feel")); if (cfg.readEntry("Show splashscreen", _ShowSplashScreen)) { QString splashFilename = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("splash.png")); QPixmap pixmap(splashFilename); if (!pixmap.isNull()) { splash = new QSplashScreen(pixmap); splash->show(); } } } // don't remove bracket Krusader::AppName = appName; Krusader *krusader = new Krusader(parser); if(!url.isEmpty()) krusader->openUrl(url); QDBusConnection dbus = QDBusConnection::sessionBus(); if (!dbus.interface()->isServiceRegistered("org.krusader") && !dbus.registerService("org.krusader")) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } if (!dbus.registerObject("/Instances/" + appName, krusader, QDBusConnection::ExportScriptableSlots)) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } if (!dbus.registerObject("/Instances/" + appName + "/left_manager", LEFT_MNG, QDBusConnection::ExportScriptableSlots)) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } if (!dbus.registerObject("/Instances/" + appName + "/right_manager", RIGHT_MNG, QDBusConnection::ExportScriptableSlots)) { fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } qDebug() << "Qt icon theme: " << QIcon::themeName(); // catching SIGTERM, SIGHUP, SIGQUIT signal(SIGTERM, sigterm_handler); signal(SIGPIPE, sigterm_handler); signal(SIGHUP, sigterm_handler); QObject::connect(&app, &QGuiApplication::applicationStateChanged, SLOTS, &KRslots::applicationStateChanged); // hide splashscreen if (splash) { splash->finish(krusader); delete splash; } // let's go. return app.exec(); }