rodlie / qtfm

Qt File Manager
https://qtfm.eu
GNU General Public License v2.0
156 stars 43 forks source link

Intra-directory copy #159

Open slackuser0xae34 opened 4 years ago

slackuser0xae34 commented 4 years ago

Expected behavior

Qtfm 6.3.0 has a bug when copying within a single directory (an intra-directory copy). The copies would be pasted, in the same directory as the source files, according to the file name template in "Edit -> Settings -> Advanced -> Destination" This type of copying worked fine in Qtfm 6.2.0 and previous.

Observed behavior

A popup window appears asking to "skip/skip all/overwrite/overwrite all". Obviously "skip/skip all" is useless for intra-directory copy. The "overwrite/overwrite all" destroys the source file(s), very bad.

Steps to reproduce or sample file

Operating System and Qtfm version info

Slackware Linux 14.2 (fully patched) Qtfm 6.3 (latest qtfm-master)

Technical description and prototype patch

Qtfm 6.3.0 has a bug when copying within a single directory (an intra-directory copy). If the destination directory is also the source directory a problem occurs. During such a copy,a popup window appear asking to "skip/skip all/overwrite/overwrite all". Obviously "skip/skip all" is useless for intra-directory copy. The "overwrite/overwrite all" destroys the source file, very bad.

This type of copying worked fine in Qtfm 6.2.0 and previous.

IMHO, this is a serious bug. I use intra-directory copying for making backups, for making test versions (which may be kept or destroyed) for making temp files, for making base files from which several variations are later made. In the short term, I went back to QTFM 6.2.0.

However, I have created a solution. The solution is a real hack, it isn't in the "spirit" of C++ and all the magic that surrounds it. The hack uses portions of code from QTFM 6.2.0 (from actiontriggers.cpp, adjusted to the new environment); the portion that figures out how to create a new name for an intra-directory copy based on the template in "Edit -> Settings -> Advanced -> Destination". This 6.2.0 code is kluged onto the 6.3.0 code, in "qtfm-master/libfm/qtcopydialog/qtfilecopier.cpp".

A text description is as follows. A "diff" is at the end. Change the source code and compile/package as usual:

#####################

In the file "qtfm-master/libfm/qtcopydialog/qtfilecopier.cpp". Starting from the end of the file, working toward the beginning (the line numbers work better this way).

Starting from the end of the file, working forward (the numbers work better this way)

Edit, 2020/02/25: Sorry I forgot, I license the following code under the GPL V2 (or later at the user's discression):

From: Lines 1005 through 1008 if (checkPath && fid.isDir()) { QDir destDir(fid.filePath()); fid.setFile(destDir, fis.fileName()); }

To if (checkPath && fid.isDir()) { QDir destDir(fid.filePath());

    // Only do 'Copy(x) of' if same folder
    if ( fis.absolutePath() != fid.filePath() ) {
        fid.setFile(destDir, fis.fileName());
    }
    else {

// // Gaaa, crude, blech // %1 = num copy // %2 = orig filename (example.tar.gz) // %3 = timestamp (yyyyMMddHHmmss, use 'copyXofTS' to override) // %4 = orig suffix (example.tar.gz=>tar.gz) // %5 = orig basename (example.tar.gz=>example) int num = 1; QString destName = fis.fileName(); while (fid.exists()) { QFileInfo fileInfo(fis.fileName()); destName = copyXof; if (destName.contains("%1")) { destName.replace("%1", QString::number(num)); } if (destName.contains("%2")) { destName.replace("%2", fileInfo.fileName()); } if (destName.contains("%3")) { destName.replace("%3", QDateTime::currentDateTime().toString(copyXofTS)); } if (destName.contains("%4")) { destName.replace("%4", fileInfo.completeSuffix()); } if (destName.contains("%5")) { destName.replace("%5", fileInfo.baseName()); } num++; fid.setFile(destDir, destName); } // } }

 ####################

Insert after: Line 1001 (which is a { )

QSettings *settings;
settings = new QSettings(Common::configFile(), QSettings::IniFormat);
QString copyXof   = settings->value("copyXof",   MIME_APPS).toString();
QString copyXofTS = settings->value("copyXofTS", MIME_APPS).toString();
delete settings;

//

 ####################

At: Line 65 (which is blank)

 #include <QSettings>
 #include <QDateTime>

 ####################

At: Line 46 (which is blank)

include "../common.h"

 #################################################################
 #################################################################
 # A diff follows, delete the 5 leading spaces to use the diff as a patch file
  --- qtfilecopier.original.cpp 2020-01-10 16:58:11.449708925 -0500
 +++ qtfilecopier.cpp   2020-01-11 09:03:46.794290962 -0500
 @@ -44,6 +44,8 @@
  ** 
  ****************************************************************************/

 +#include "../common.h"
 +
  #include "qtfilecopier.h"
  #include <QtCore/QThread>
  #include <QtCore/QMutex>
 @@ -59,6 +61,9 @@
  #include <QtCore/QMetaType>
  #include <QDebug>

 +#include <QSettings>
 +#include <QDateTime>
 +
  struct CopyRequest {
      CopyRequest() {
          move = false;
 @@ -999,12 +1004,55 @@
  CopyRequest QtFileCopierPrivate::prepareRequest(bool checkPath, const QString &sourceFile,
          const QString &destinationPath, QtFileCopier::CopyFlags flags, bool move, bool dir) const
  {
 +    QSettings *settings;
 +    settings = new QSettings(Common::configFile(), QSettings::IniFormat);
 +    QString copyXof   = settings->value("copyXof",   MIME_APPS).toString();
 +    QString copyXofTS = settings->value("copyXofTS", MIME_APPS).toString();
 +    delete settings;
 +//
      QFileInfo fis(sourceFile);
      QFileInfo fid(destinationPath);
      fid.makeAbsolute();
      if (checkPath && fid.isDir()) {
          QDir destDir(fid.filePath());
 -        fid.setFile(destDir, fis.fileName());
 +
 +        // Only do 'Copy(x) of' if same folder
 +        if ( fis.absolutePath() != fid.filePath() ) {
 +            fid.setFile(destDir, fis.fileName());
 +        }
 +        else {
 +//
 +// Gaaa, crude, blech
 +            // %1 = num copy
 +            // %2 = orig filename (example.tar.gz)
 +            // %3 = timestamp (yyyyMMddHHmmss, use 'copyXofTS' to override)
 +            // %4 = orig suffix (example.tar.gz=>tar.gz)
 +            // %5 = orig basename (example.tar.gz=>example)
 +            int num = 1;
 +            QString destName = fis.fileName();
 +            while (fid.exists()) {
 +                QFileInfo fileInfo(fis.fileName());
 +                destName = copyXof;
 +                if (destName.contains("%1")) {
 +                    destName.replace("%1", QString::number(num));
 +                }
 +                if (destName.contains("%2")) {
 +                    destName.replace("%2", fileInfo.fileName());
 +                }
 +                if (destName.contains("%3")) {
 +                    destName.replace("%3", QDateTime::currentDateTime().toString(copyXofTS));
 +                }
 +                if (destName.contains("%4")) {
 +                    destName.replace("%4", fileInfo.completeSuffix());
 +                }
 +                if (destName.contains("%5")) {
 +                    destName.replace("%5", fileInfo.baseName());
 +                }
 +                num++;
 +            fid.setFile(destDir, destName);
 +            }
 +//
 +        }
      }
      CopyRequest r;
      r.source = fis.filePath();

 # End of diff
 # Sorry, Git (aka Microsoft) and I have an intense difference of 
 # opinion regarding JavaScript,thus I can't upload a zip file with the diff.
 #############################################################

The fact this hack works (for me), though I can't see the devs using it directly. If the devs decide to address this issue, they will create something more in line with the philosophy of C++ and consistent with the basic design of the code. Me, I'm an old fashioned hacker, I want the code to work first then the "niceties" are dealt with later if needed or desirable. S.