[qc_.*cpp] Error 1问题的原因与解决方法

概要

1)现象:编译时报[qc_.*cpp] Error 1

2)解决方法:去掉与上面文件名中的”*“同名的文件(*.qrc)文件中有无效的资源路径,即这些路径所对应的文件已经不存在。因此,要么恢复这些资源文件,要么从资源列表中删除这些资源路径。


详细分析:

       在编译qt程序时,有时候会遇到RT所述的问题,导致编译不成功,但是未提供更多额外的错误信息,且无法跟进去,使我们无法定位问题所在。非常苦恼,如果不把该问题弄清楚,以后还是会遇到类似问题。为此,把对该问题的分析和解决方法做一下记录,以备后查。


        其实,这个问题也还是有索可循的,从仅有的极其少量信息里唯一能够获取的提示是和该文件有关系。那么,在这种情况下,直接去代码文件系统里是找不到该文件的,因为它是另一个文件生成的。而这个文件就是与“*.qrc“同名的一个资源文件。故,可以把焦点聚集到该资源文件上。

        仔细比较该资源文件中的资源名状态,可以发现,一些资源(尤其是图片资源)的状态处于无法定位到目标资源的情况(这种情况下的表现是:资源路径前面无缩略图),所以需要恢复这些资源文件,或者是在*.qrc文件中将无效的资源路径删除,重新编译即可。

        至此,问题应该能得到彻底解决。


/**************************************************************************** ** ** This file is part of the LibreCAD project, a 2D CAD program ** ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl) ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. ** ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file gpl-2.0.txt included in the ** packaging of this file. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** This copyright notice MUST APPEAR in all copies of the script! ** **********************************************************************/ #include "main.h" #include <qapplication.h> #include <QSplashScreen> QSplashScreen *splash; #ifdef RS_SCRIPTING #include <qsproject.h> #endif #include "rs_fontlist.h" #include "rs_patternlist.h" #include "rs_scriptlist.h" #include "rs_settings.h" #include "rs_system.h" #include "rs_fileio.h" #include "rs_filtercxf.h" #include "rs_filterdxf.h" #include "rs_filterdxf1.h" #include "rs_filterlff.h" #include "qg_dlginitial.h" #include "qc_applicationwindow.h" #ifndef QC_SPLASH_TXTCOL # define QC_SPLASH_TXTCOL Qt::black #endif // for image mime resources from png files extern void QINITIMAGES_LIBRECAD(); #ifdef RS_SCRIPTING // extern void qInitImages_LibreCAD(); #endif #ifdef QC_BUILTIN_STYLE extern void applyBuiltinStyle(); #endif /** * Main. Creates Application window. * * Cleaning up #defines. */ int main(int argc, char** argv) { RS_DEBUG->setLevel(RS_Debug::D_WARNING); RS_DEBUG->print("param 0: %s", argv[0]); QCoreApplication::setApplicationName(XSTR(QC_APPNAME)); QCoreApplication::setApplicationVersion(XSTR(QC_VERSION)); QApplication app(argc, argv); // for image mime resources from png files // TODO: kinda dirty to call that explicitly QINITIMAGES_LIBRECAD(); #ifdef RS_SCRIPTING // qInitImages_librecad(); #endif for (int i=0; i<app.argc(); i++) { if (QString("--debug") == app.argv()[i]) { RS_DEBUG->setLevel(RS_Debug::D_DEBUGGING); } } QFileInfo prgInfo( QFile::decodeName(argv[0]) ); QString prgDir(prgInfo.dirPath(true)); RS_SETTINGS->init(XSTR(QC_COMPANYKEY), XSTR(QC_APPKEY)); RS_SYSTEM->init(XSTR(QC_APPNAME), XSTR(QC_VERSION), XSTR(QC_APPDIR), prgDir); RS_FILEIO->registerFilter(new RS_FilterLFF()); RS_FILEIO->registerFilter(new RS_FilterCXF()); RS_FILEIO->registerFilter(new RS_FilterDXF()); RS_FILEIO->registerFilter(new RS_FilterDXF1()); // parse command line arguments that might not need a launched program: QStringList fileList = handleArgs(argc, argv); QString lang; QString langCmd; QString unit; RS_SETTINGS->beginGroup("/Defaults"); #ifndef QC_PREDEFINED_UNIT unit = RS_SETTINGS->readEntry("/Unit", "Invalid"); #else unit = RS_SETTINGS->readEntry("/Unit", QC_PREDEFINED_UNIT); #endif RS_SETTINGS->endGroup(); // show initial config dialog: if (unit=="Invalid") { RS_DEBUG->print("main: show initial config dialog.."); QG_DlgInitial di(NULL); di.setText("<font size=\"+1\"><b>Welcome to " XSTR(QC_APPNAME) "</b></font>" "<br>" "Please choose the unit you want to use for new drawings and your " "preferred language.<br>" "You can changes these settings later in the " "Options Dialog of " XSTR(QC_APPNAME) "."); QPixmap pxm(":/main/intro_librecad.png"); di.setPixmap(pxm); if (di.exec()) { RS_SETTINGS->beginGroup("/Defaults"); unit = RS_SETTINGS->readEntry("/Unit", "None"); RS_SETTINGS->endGroup(); } RS_DEBUG->print("main: show initial config dialog: OK"); } #ifdef QSPLASHSCREEN_H RS_DEBUG->print("main: splashscreen.."); QPixmap* pixmap = new QPixmap(":/main/splash_librecad.png"); # endif RS_DEBUG->print("main: init fontlist.."); RS_FONTLIST->init(); RS_DEBUG->print("main: init fontlist: OK"); RS_DEBUG->print("main: init patternlist.."); RS_PATTERNLIST->init(); RS_DEBUG->print("main: init patternlist: OK"); RS_DEBUG->print("main: init scriptlist.."); RS_SCRIPTLIST->init(); RS_DEBUG->print("main: init scriptlist: OK"); RS_DEBUG->print("main: loading translation.."); RS_SETTINGS->beginGroup("/Appearance"); #ifdef QC_PREDEFINED_LOCALE lang = RS_SETTINGS->readEntry("/Language", ""); if (lang.isEmpty()) { lang=QC_PREDEFINED_LOCALE; RS_SETTINGS->writeEntry("/Language", lang); } langCmd = RS_SETTINGS->readEntry("/LanguageCmd", ""); if (langCmd.isEmpty()) { langCmd=QC_PREDEFINED_LOCALE; RS_SETTINGS->writeEntry("/LanguageCmd", langCmd); } #else lang = RS_SETTINGS->readEntry("/Language", "en"); langCmd = RS_SETTINGS->readEntry("/LanguageCmd", "en"); #endif RS_SETTINGS->endGroup(); RS_SYSTEM->loadTranslation(lang, langCmd); RS_DEBUG->print("main: loading translation: OK"); #ifdef QSPLASHSCREEN_H splash = new QSplashScreen(*pixmap); splash->show(); splash->message(QObject::tr("Loading.."), Qt::AlignRight|Qt::AlignBottom, QC_SPLASH_TXTCOL); RS_DEBUG->print("main: splashscreen: OK"); #endif //QApplication::setStyle(new QWindowsStyle()); //QApplication::setStyle(new QPlatinumStyle()); #ifdef QC_BUILTIN_STYLE //js: RS_DEBUG->print("main: applying built in style.."); applyBuiltinStyle(); #endif RS_DEBUG->print("main: creating main window.."); QC_ApplicationWindow * appWin = new QC_ApplicationWindow(); RS_DEBUG->print("main: setting caption"); appWin->setCaption(XSTR(QC_APPNAME)); RS_DEBUG->print("main: show main window"); appWin->show(); RS_DEBUG->print("main: set focus"); appWin->setFocus(); RS_DEBUG->print("main: creating main window: OK"); #ifdef QSPLASHSCREEN_H if (splash) { RS_DEBUG->print("main: updating splash.."); splash->message(QObject::tr("Loading..."), Qt::AlignRight|Qt::AlignBottom, QC_SPLASH_TXTCOL); RS_DEBUG->print("main: processing events"); qApp->processEvents(); RS_DEBUG->print("main: updating splash: OK"); } #endif // Set LC_NUMERIC so that enetring numeric values uses . as teh decimal seperator setlocale(LC_NUMERIC, "C"); RS_DEBUG->print("main: loading files.."); bool files_loaded = false; for (QStringList::Iterator it = fileList.begin(); it != fileList.end(); ++it ) { #ifdef QSPLASHSCREEN_H if (splash) { splash->message(QObject::tr("Loading File %1..") .arg(QDir::convertSeparators(*it)), Qt::AlignRight|Qt::AlignBottom, QC_SPLASH_TXTCOL); qApp->processEvents(); } #endif appWin->slotFileOpen(*it, RS2::FormatUnknown); files_loaded = true; } RS_DEBUG->print("main: loading files: OK"); #ifdef QSPLASHSCREEN_H # ifndef QC_DELAYED_SPLASH_SCREEN if (splash) { splash->finish(appWin); delete splash; splash = 0; } # endif delete pixmap; #endif //app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); RS_DEBUG->print("main: app.exec()"); if (!files_loaded) { appWin->slotFileNew(); } appWin->slotRunStartScript(); int r = app.exec(); RS_DEBUG->print("main: Temporary disabled delete appWin"); // delete appWin; RS_DEBUG->print("main: finished"); return r; } /** * Handles command line arguments that might not require a GUI. * * @return list of files to load on startup. */ QStringList handleArgs(int argc, char** argv) { RS_DEBUG->print("main: handling args.."); QStringList ret; bool doexit = false; QString machine; QString input; QString output; for (int i=1; i<argc; i++) { if (QString(argv[i]).startsWith("-")==false) { QString fname = QDir::convertSeparators( QFileInfo(QFile::decodeName(argv[i])).absFilePath() ); ret.append(fname); } else if (QString(argv[i])=="--exit") { doexit = true; } } if (doexit) { exit(0); } RS_DEBUG->print("main: handling args: OK"); return ret; } 给这些代码加上注释
07-04
[ 81%] Linking CXX shared library G:\czg\ewbvision\ewb_ai_20250521_00001\EWB_AI_VISION\Plugins\libScriptEdit.dll C:\cmake-4.0.0-windows-x86_64\bin\cmake.exe -E rm -f CMakeFiles\ScriptEdit.dir/objects.a C:\Qt\Tools\mingw810_64\bin\ar.exe qc CMakeFiles\ScriptEdit.dir/objects.a @CMakeFiles\ScriptEdit.dir\objects1.rsp C:\Qt\Tools\mingw810_64\bin\g++.exe -DQT_QML_DEBUG -g -shared -o G:\czg\ewbvision\ewb_ai_20250521_00001\EWB_AI_VISION\Plugins\libScriptEdit.dll -Wl,--out-implib,libScriptEdit.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -Wl,--whole-archive CMakeFiles\ScriptEdit.dir/objects.a -Wl,--no-whole-archive @CMakeFiles\ScriptEdit.dir\linkLibs.rsp CMakeFiles\ScriptEdit.dir/objects.a(ScriptEditFun.cpp.obj): In function `JS_AtomToCString': G:/czg/ewbvision/ewb_ai_20250604-00001/EWB_AIMachineVisionInspection/ScriptEdit/quickjs/quickjs.h:462: undefined reference to `JS_AtomToCStringLen' CMakeFiles\ScriptEdit.dir/objects.a(ScriptEditFun.cpp.obj): In function `JS_ToQVariant(JSContext*, JSValue)': G:/czg/ewbvision/ewb_ai_20250604-00001/EWB_AIMachineVisionInspection/ScriptEdit/ScriptEditFun.cpp:412: undefined reference to `JS_FreePropertyEnum' collect2.exe: error: ld returned 1 exit status mingw32-make.exe[3]: *** [ScriptEdit\CMakeFiles\ScriptEdit.dir\build.make:320: G:/czg/ewbvision/ewb_ai_20250521_00001/EWB_AI_VISION/Plugins/libScriptEdit.dll] Error 1 mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:2348: ScriptEdit/CMakeFiles/ScriptEdit.dir/all] Error 2 mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:2355: ScriptEdit/CMakeFiles/ScriptEdit.dir/rule] Error 2 mingw32-make.exe: *** [Makefile:870: ScriptEdit] Error 2 13:56:44: 进程"C:\cmake-4.0.0-windows-x86_64\bin\cmake.exe"退出,退出代码 2 。 13:56:44: Error while building/deploying project EWB (kit: Desktop Qt 5.15.0 MinGW 64-bit) 13:56:44: When executing step "构建"
06-06
#include "QFtpClient.h" #include <QDir> #include <QFileInfo> #include <QObject> #include <QEventLoop> #include "log.h" QDateTime start_t; void set_start() { start_t = QDateTime::currentDateTime(); } void time_span() { KOE_DEBUG(QObject::tr("spend time:%1ms").arg(start_t.msecsTo(QDateTime::currentDateTime()))); } struct SingleCmd { QFtp::Command cmd = QFtp::None; int state = 0; // 0 - prepare, 1 - doing, 2 - done QVariantList vParam; SingleCmd(QFtp::Command c = QFtp::None) { cmd = c; } bool is_valid()const { return cmd != QFtp::None; } void reset() { cmd = QFtp::None; } bool operator == (const SingleCmd& other) { if (cmd == other.cmd) { if (cmd == QFtp::List) { return true; } else if (vParam.isEmpty() || other.vParam.isEmpty()) { return false; } else { return vParam.front().toString() == other.vParam.front().toString(); } } else { return false; } } }; bool in_stringlist(const QString& sFind, const QStringList& v) { for (auto s : v) { if (sFind.contains(s)) return true; } return false; } QVariantList stringlist_varlist(const QStringList& vstring) { QVariantList ret; for (auto s : vstring) { ret.append(s); } return ret; } QStringList varlist_stringlist(const QVariantList& varlist) { QStringList ret; for (auto var : varlist) { ret.append(var.toString()); } return ret; } QFtpClient::QFtpClient(QString serverip, QString username, QString password, qint16 port, QObject* parent) : QFtp(parent) { setIP(serverip, port); setUser(username, password); m_pConnect = new QTimer(this); connect(this, SIGNAL(stateChanged(int)), this, SLOT(slot_state_changed(int))); connect(m_pConnect, SIGNAL(timeout()), this, SLOT(slot_timer_connect())); connect(this, SIGNAL(commandFinished(int, bool)), this, SLOT(slot_finish(int, bool))); connect(this, SIGNAL(listInfo(const QUrlInfo&)), this, SLOT(slot_listinfo(const QUrlInfo&))); connect(this, SIGNAL(signal_command_finish(int, QVariantList, QString)), this, SLOT(slot_inner_cmd(int, QVariantList, QString))); } QFtpClient::~QFtpClient() { if (m_buffer) { m_buffer->deleteLater(); m_buffer = 0; } close_host(); if (m_pConnect) { m_pConnect->deleteLater(); m_pConnect = 0; } } void QFtpClient::setIP(const QString& ip, const qint16 port) { m_url.setHost(ip); m_url.setPort(port); } void QFtpClient::setUser(const QString& username, const QString& password) { m_url.setUserName(username); m_url.setPassword(password); } void QFtpClient::slot_finish(int id, bool berror) { SingleCmd& smd = m_mapCmd[id]; smd.state = 2; QString errstr = berror ? errorString() : ""; switch (currentCommand()) { case QFtp::ConnectToHost: connect_result(errstr); return; case QFtp::Login: login_result(errstr); return; case QFtp::Close: close_result(errstr); break; case QFtp::List: { m_prevlistcmd = m_listcmd; list_result(smd); }break; case QFtp::Get: get_result(smd, errstr); break; case QFtp::Cd: cd_result(smd, errstr); break; case QFtp::Put: put_result(smd, errstr); break; case QFtp::Mkdir: mkd_result(smd, errstr); break; case QFtp::Rmdir: rmd_result(smd, errstr); break; case QFtp::Remove: rm_result(smd, errstr); break; case QFtp::Rename: rename_result(smd, errstr); break; default: break; } if (!m_lCmd.isEmpty() && smd == m_lCmd.front()) m_lCmd.pop_front(); if (m_lCmd.isEmpty() && !m_rmlist.isEmpty()) { m_lCmd.append(m_rmlist); m_rmlist.clear(); } m_mapCmd.remove(id); next_cmd(); } void QFtpClient::slot_listinfo(const QUrlInfo& url) { if (m_mapCmd.isEmpty()) return; switch (m_listcmd) { case QFtp::Get: { if (url.isFile()) { if (!in_stringlist(url.name(), m_vExcept.toList())) { SingleCmd smd; smd.cmd = QFtp::Get; smd.vParam.append(m_CurrentPath.second + "/" + url.name()); smd.vParam.append(url.name()); // if get, append local file path smd.vParam.append(m_CurrentPath.first + "/" + url.name()); m_lCmd.append(smd); inc_record(rt_total); } } else if (url.isDir() && url.name() != "." && url.name() != "..") { if(!in_stringlist(url.name(), m_vExcept.toList())){ m_PendingPath.append(qMakePair(m_CurrentPath.first + "/" + url.name(), m_CurrentPath.second + "/" + url.name())); if (!m_CurrentPath.first.isEmpty()) QDir(m_CurrentPath.first).mkpath(url.name()); } } }break; case QFtp::Rmdir: { if (url.isFile()) { build_cd_cmd(pwd()); SingleCmd smd; smd.cmd = QFtp::Remove; smd.vParam.append(url.name()); smd.vParam.append(pwd() + "/" + url.name()); m_lCmd.append(smd); inc_record(rt_total); } else if (url.isDir() && url.name() != "." && url.name() != "..") { build_cd_cmd(pwd() + '/' + url.name()); SingleCmd smd; smd.cmd = QFtp::List; smd.vParam.append(pwd() + '/' + url.name()); m_lCmd.append(smd); QList<SingleCmd> cdcmd; build_cd_cmd(pwd(), cdcmd); smd.cmd = QFtp::Rmdir; smd.vParam.clear(); smd.vParam.append(pwd() + '/' + url.name()); smd.vParam.append(url.name()); cdcmd.append(smd); cdcmd.append(m_rmlist); m_rmlist = cdcmd; } }break; case QFtp::List: { if (url.name() != "." && url.name() != "..") m_listresult.append(url); }break; default: break; } } void QFtpClient::slot_inner_cmd(int cmdid, QVariantList params, QString errorstring) { switch (cmdid) { case QFtp::ConnectToHost: { if (errorstring.isEmpty()) emit signal_ftp_log("Success to connect ftp"); else emit signal_ftp_log(QString("Fail to connect ftp, reason:").append(errorstring), true); } break; case QFtp::Login: { if (errorstring.isEmpty()) emit signal_ftp_log("Success to login ftp"); else emit signal_ftp_log(QString("Fail to login ftp, reason:").append(errorstring), true); } break; case QFtp::Close: { if (errorstring.isEmpty()) emit signal_ftp_log("Success to close ftp"); else emit signal_ftp_log(QString("Fail to close ftp, reason:").append(errorstring), true); } break; case QFtp::Get: { if (params.size() > 2) { QString remotefilepath = params[0].toString(), remotefilename = params[1].toString(), localfilepath = params[2].toString(); if (errorstring.isEmpty()) emit signal_ftp_log(QString("Get file:%1 -> %2").append(remotefilepath).arg(localfilepath)); else emit signal_ftp_log(QString("Fail to get:%1 -> %2").append(remotefilepath).arg(localfilepath), true); } else if (!errorstring.isEmpty()) emit signal_ftp_log(errorstring, true); } break; case QFtp::Cd: { if (!params.isEmpty()) { if (!errorstring.isEmpty()) emit signal_ftp_log(QString("Directory:%1 not exist").append(params.front().toString()), true); } } break; case QFtp::Put: { if (params.size() > 2) { QString localfile = params[0].toString(), remotefilename = params[1].toString(), remotefile = params[2].toString(); if (errorstring.isEmpty()) emit signal_ftp_log(QString("Put file:%1 -> %2").arg(localfile).arg(remotefile)); else emit signal_ftp_log(QString("Fail to put:%1 -> %2").append(localfile).arg(remotefile), true); } else if (!errorstring.isEmpty()) emit signal_ftp_log(errorstring, true); } break; case QFtp::Remove: { if (params.size() > 1) { QString remotefilepath = params[0].toString(), remotefilename = params[1].toString(); if (errorstring.isEmpty()) emit signal_ftp_log(QString("Remove file:%1").arg(remotefilepath)); else emit signal_ftp_log(QString("Fail to remove:%1").append(remotefilepath), true); } else if (!errorstring.isEmpty()) emit signal_ftp_log(errorstring, true); } break; case QFtp::Rmdir: { if (params.size() > 1) { QString remotepath = params[0].toString(), remotefoldername = params[1].toString(); if (errorstring.isEmpty()) emit signal_ftp_log(QString("rmdir:%1").arg(remotepath)); } }break; case QFtp::Rename: { if (params.size() > 2) { QString remotepath = params[0].toString(), remotetargetname = params[1].toString(), remotenewname = params[2].toString(); if (errorstring.isEmpty()) emit signal_ftp_log(QString("rename:%1 -> %2").arg(remotepath).arg(remotenewname)); } }break; default: break; } } void QFtpClient::slot_state_changed(int value) { emit signal_state_changed(value); if (value != QFtp::LoggedIn) m_PathSection.clear(); } void QFtpClient::slot_timer_connect() { switch (state()) { case QFtp::Unconnected: { KOE_DEBUG(tr("try to connect ftp server")); connectToHost(m_url.host(), m_url.port()); }break; case QFtp::LoggedIn: { if (m_pConnect) m_pConnect->stop(); }break; case Connected: { KOE_DEBUG(tr("try to login ftp server")); login(m_url.userName(), m_url.password()); }break; default: break; } } void QFtpClient::connect_host() { switch (state()) { case QFtp::Connected: break; case QFtp::Unconnected: { if (m_pConnect) { if (!m_pConnect->isActive()) { connectToHost(m_url.host(), m_url.port()); m_pConnect->start(1000); } } }break; case HostLookup: case Connecting: { KOE_DEBUG(tr("connecting to ftp server")); }break; case LoggedIn: { KOE_DEBUG(tr("already connected to ftp server")); }break; case Closing: { KOE_DEBUG(tr("ftp closing")); }break; default: break; } } bool QFtpClient::sync_connect(int msec) { bool ok = false; if (state() != QFtp::Unconnected) { KOE_WARN(tr("Fail to connect to ftp for current state not unconnected")); return false; } QEventLoop* e = new QEventLoop; QTimer* tOut = new QTimer; tOut->setInterval(msec); QMetaObject::Connection ok_cnt = connect(this, &QFtp::stateChanged, [&](int state) { if (state == QFtp::LoggedIn) { ok = true; KOE_INFO(tr("Success to connect to ftp server and login")); if (e && e->isRunning()) { e->quit(); } } } ); QMetaObject::Connection timer_cnt = connect(tOut, &QTimer::timeout, [&] { ok = false; KOE_WARN(tr("Fail to connect to ftp server for timeout")); if (e && e->isRunning()) { e->quit(); } } ); tOut->start(); connect_host(); e->exec(); if (m_pConnect && m_pConnect->isActive()) m_pConnect->stop(); if (tOut) { if (tOut->isActive()) tOut->stop(); delete tOut; tOut = 0; } if (e) { delete e; e = 0; } disconnect(ok_cnt); disconnect(timer_cnt); return ok; } void QFtpClient::close_host() { clear_cmd(); close(); if (m_pConnect) { if (m_pConnect->isActive()) m_pConnect->stop(); } //if (state() == QFtp::Closing || state() == QFtp::Unconnected) return; } bool QFtpClient::get_buffer(const QString& remoteabsfile, int msec) { const QString strcmd = tr("get buffer"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_get_buffer(remoteabsfile, msec); } bool QFtpClient::get_file(const QString& remoteabsfile, const QString& localabsfile, int msec) { const QString strcmd = tr("get file"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_get_file(remoteabsfile, localabsfile, msec); } bool QFtpClient::get_files(const QList< QPair<QString, QString> >& vfiles, int msec) { const QString strcmd = tr("get buffer"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; if (vfiles.isEmpty()) return false; QVariantList varlist; for (auto ppair : vfiles) varlist << ppair.first << ppair.second; return inner_get_files(varlist, msec); } bool QFtpClient::get_tree(const QString& remoteabspath, const QString& localabspath, const QStringList& exceptabspath, int msec) { const QString strcmd = tr("get tree"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_get_tree(remoteabspath, localabspath, exceptabspath, msec); } bool QFtpClient::put_files(const QList< QPair<QString, QString> >& vfiles, int msec) { const QString strcmd = tr("get files"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; if (vfiles.isEmpty()) return false; QVariantList varlist; for (auto ppair : vfiles) varlist << ppair.first << ppair.second; return inner_put_files(varlist, msec); } bool QFtpClient::put_file(const QString& localabsfile, const QString& remoteabsfile, int msec) { const QString strcmd = tr("put file"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_put_file(localabsfile, remoteabsfile, msec); } bool QFtpClient::put_tree(const QString& localabspath, const QString& remoteabspath, const QStringList& exceptpath, int msec) { const QString strcmd = tr("put tree"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_put_tree(localabspath, remoteabspath, exceptpath, msec); } bool QFtpClient::mk_dir(const QString& dir, int msec) { const QString strcmd = tr("mk dir"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_mk_dir(dir, msec); } bool QFtpClient::mk_dir(const QStringList& dirlist, int msec) { const QString strcmd = tr("mk multi dir"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_mk_dir(dirlist, msec); } bool QFtpClient::rm_tree(const QString& dir, int msec) { const QString strcmd = tr("rm tree"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_rm_tree(dir, msec); } bool QFtpClient::rm_file(const QString& remotefile, int msec) { const QString strcmd = tr("rm file"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_rm_file(remotefile, msec); } bool QFtpClient::_rename(const QString& remotefilepath, const QString& newname, int msec) { const QString strcmd = tr("rename"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_rename(remotefilepath, newname, msec); } bool QFtpClient::_list(const QString& remotepath, int msec) { const QString strcmd = tr("list"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_list(remotepath, msec); } bool QFtpClient::pwd_put_file(const QString& localabsfile, int msec) { const QString strcmd = tr("put pwd file"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_put_file(localabsfile, "", msec); } bool QFtpClient::pwd_get_file(const QString& remotefile, const QUrl& localurl, int msec) { const QString strcmd = tr("get pwd file"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; QString slocal = localurl.path(); if (slocal.startsWith('/')) slocal = slocal.mid(1); if (!slocal.endsWith('/')) slocal += '/'; return inner_get_file(remotefile, slocal, msec); } bool QFtpClient::pwd_rm_file(const QString& remotefile, int msec) { const QString strcmd = tr("remove pwd file"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_rm_file(remotefile, msec); } bool QFtpClient::pwd_rm_tree(const QString& dir, int msec) { const QString strcmd = tr("remove pwd tree"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_rm_tree(dir, msec); } bool QFtpClient::pwd_mk_dir(const QString& remotedir, int msec) { return false; } bool QFtpClient::pwd_rename(const QString& remotefile, const QString& newname, int msec) { const QString strcmd = tr("rename"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_rename(remotefile, newname, msec); } bool QFtpClient::pwd_list(int msec) { return _list("", msec); } bool QFtpClient::pwd_cd(const QString& dirname, bool done_list, int msec) { const QString strcmd = tr("cd"); if (is_busy()) { KOE_WARN(tr("fail to %1: busy").arg(strcmd)); return false; } bool isAlive = is_connect(); if (!isAlive) isAlive = sync_connect(); if (!isAlive) return false; return inner_cd(dirname, done_list, msec); } bool QFtpClient::is_busy()const { return !m_lCmd.isEmpty(); } bool QFtpClient::is_connect()const { return state() == QFtp::LoggedIn; } QString QFtpClient::pwd() { return QString("/%1").arg(m_PathSection.join('/')); } void QFtpClient::connect_result(QString errstr) { if (errstr.isEmpty()) { KOE_DEBUG(tr("Success to connect ftp")); KOE_DEBUG(tr("try to login ftp server by user:%1").arg(m_url.userName())); login(m_url.userName(), m_url.password()); } else KOE_WARN(tr("Fail to connect ftp:%1").arg(errstr)); emit signal_command_finish(QFtp::ConnectToHost, {}, errstr); } void QFtpClient::login_result(QString errstr) { if (errstr.isEmpty()) { KOE_DEBUG(tr("Success to login ftp")); } else KOE_WARN(tr("Fail to login ftp:%1").arg(errstr)); emit signal_command_finish(QFtp::Login, {}, errstr); } void QFtpClient::close_result(QString errstr) { if (errstr.isEmpty()) KOE_DEBUG(tr("Success to close ftp")); else KOE_WARN(tr("Fail to close ftp:%1").arg(errstr)); emit signal_command_finish(QFtp::Close, {}, errstr); } void QFtpClient::list_result(const SingleCmd& ssmd) { if (m_mapCmd.isEmpty()) return; switch (m_prevlistcmd) { case QFtp::Get: { if (!m_PendingPath.isEmpty()) { m_CurrentPath = m_PendingPath.takeLast(); build_cd_cmd(m_CurrentPath.second); SingleCmd smd; smd.cmd = QFtp::List; m_lCmd.append(smd); m_listcmd = m_prevlistcmd; } }break; case QFtp::Rmdir: { }break; case QFtp::List: { emit signal_list(m_listresult); /*m_listcmd = QFtp::None;*/ m_prevlistcmd = QFtp::None; emit signal_command_finish(QFtp::List, QVariantList()); if (m_cmd == QC_LIST) inc_record(rt_success); }break; default: break; } } bool QFtpClient::has_cmd() { return !m_lCmd.isEmpty(); } bool QFtpClient::next_cmd() { if (!is_connect()) return false; if (m_lCmd.isEmpty()) { emit signal_done(m_cmd, success_count, execute_count, total_count); m_cmd = QC_NONE; reset_record(); } else { SingleCmd& smd = m_lCmd.front(); if (smd.state > 0) return false; smd.state = 1; switch (smd.cmd) { case QFtp::Cd: m_mapCmd.insert(cd(smd.vParam.front().toString()), smd); if (m_cmd == QC_CD) { inc_record(rt_executing); } break; case QFtp::Mkdir: m_mapCmd.insert(mkdir(smd.vParam.front().toString()), smd); if (m_cmd == QC_MKD || m_cmd == QC_MKDS) { inc_record(rt_executing); } break; case QFtp::Put: { if (smd.vParam.size() > 2) { QFile qfile(smd.vParam.front().toString()); if (qfile.open(QIODevice::ReadOnly)) { m_mapCmd.insert(put(qfile.readAll(), smd.vParam[1].toString()), smd); qfile.close(); if (m_cmd == QC_PUT_FILE || m_cmd == QC_PUT_FILES || m_cmd == QC_PUT_TREE) { inc_record(rt_executing); } } } }break; case QFtp::Get: { if (smd.vParam.size() > 1) { QString remotefilepath = smd.vParam[0].toString(), remotefilename = smd.vParam[1].toString(); if (smd.vParam.size() > 2) { QString localfilepath = smd.vParam[2].toString(); int pathindex = localfilepath.lastIndexOf('/'); QDir dpath(localfilepath.mid(0, pathindex)); if (!dpath.exists()) dpath.mkpath(dpath.path()); QFile* pFile = new QFile(localfilepath); //pFile->remove(); // if need rm ? if (pFile->open(QIODevice::WriteOnly)) { smd.vParam.append(QVariant::fromValue(pFile)); m_mapCmd.insert(get(remotefilename, pFile), smd); if (m_cmd == QC_GET_FILE || m_cmd == QC_GET_FILES || m_cmd == QC_GET_TREE) { inc_record(rt_executing); } } else { KOE_WARN(tr("fail to create file:%1").arg(localfilepath)); } } else { if (!m_buffer) m_buffer = new QBuffer(this); m_mapCmd.insert(get(remotefilename, m_buffer, QFtp::Binary), smd); if (m_cmd == QC_GET_FILE || m_cmd == QC_GET_FILES || m_cmd == QC_GET_TREE) { inc_record(rt_executing); } } } }break; case QFtp::List: m_mapCmd.insert(list(), smd); if (m_cmd == QC_LIST) inc_record(rt_executing); break; case QFtp::Rmdir: { if (smd.vParam.size() > 0) m_mapCmd.insert(rmdir(smd.vParam.front().toString()), smd); }break; case QFtp::Remove: { if (smd.vParam.size() > 0) { m_mapCmd.insert(remove(smd.vParam.front().toString()), smd); if (m_cmd == QC_RM_FILE || m_cmd == QC_RM_TREE) { inc_record(rt_executing); } } }break; case QFtp::Rename: { if (smd.vParam.size() > 2) { m_mapCmd.insert(rename(smd.vParam[1].toString(), smd.vParam[2].toString()), smd); if (m_cmd == QC_RENAME) { inc_record(rt_executing); } } }break; default: return false; } } return true; } bool QFtpClient::next_cmd_util_done(int msec) { bool ok = false; QEventLoop* e = new QEventLoop; QTimer* t = 0; QMetaObject::Connection timeoutCnt; QMetaObject::Connection doneCnt = connect(this, &QFtpClient::signal_done, [&](int cmdid, int ok_num, int exec_num, int total_num) { ok = (cmdid == m_cmd) && (exec_num == 1 ? ok_num == exec_num : true); if (e && e->isRunning()) e->quit(); } ); if (msec > 0) { t = new QTimer; t->setInterval(msec); timeoutCnt = connect(t, &QTimer::timeout, [&] { ok = false; if (!m_lCmd.isEmpty()) m_lCmd.clear(); if (e && e->isRunning()) e->quit(); } ); } if (next_cmd()) { if (t) t->start(); e->exec(); } if (t) { delete t; t = 0; } if (e) { delete e; e = 0; } disconnect(doneCnt); disconnect(timeoutCnt); return ok; } void QFtpClient::cd_result(const SingleCmd& smd, QString errstr) { if (m_mapCmd.isEmpty()) return; if (smd.is_valid()) { QString param = smd.vParam.isEmpty() ? "" : smd.vParam.front().toString(); if (!errstr.isEmpty()) { KOE_WARN(tr("Fail to cd to:%1, for reason:%2").arg(param).arg(errstr)); emit signal_command_finish(QFtp::Cd, smd.vParam, errstr); return; } if (smd.vParam[0].toString() == "/") m_PathSection.clear(); else if (smd.vParam[0].toString() == "..") { if (!m_PathSection.isEmpty()) m_PathSection.pop_back(); } else m_PathSection.append(smd.vParam[0].toString()); if (smd.vParam.size() > 1) { if (smd.vParam[1].toInt() > 0) { QTimer::singleShot(100, [=] { pwd_list(); }); } // done_list emit signal_command_finish(QFtp::Cd, smd.vParam); if (m_cmd == QC_CD) { inc_record(rt_success); } } } } void QFtpClient::put_result(const SingleCmd& smd, QString errstr) { if (m_mapCmd.isEmpty()) return; if (smd.is_valid()) { if (smd.vParam.size() > 2) { QString localfile = smd.vParam[0].toString(), remotefilename = smd.vParam[1].toString(), remotefile = smd.vParam[2].toString(); if (errstr.isEmpty()) { KOE_DEBUG(tr("success put:%1 -> %2").arg(localfile).arg(remotefile)); if (m_cmd == QC_PUT_FILE || m_cmd == QC_PUT_FILES || m_cmd == QC_PUT_TREE) inc_record(rt_success); } else KOE_WARN(tr("Fail to put:%1 -> %2, for reason:%3").arg(localfile).arg(remotefile).arg(errorString())); } else KOE_WARN(tr("param error")); } emit signal_command_finish(QFtp::Put, smd.vParam, errstr); #ifdef _DEBUG time_span(); #endif } void QFtpClient::mkd_result(const SingleCmd& smd, QString errstr) { Q_UNUSED(smd); Q_UNUSED(errstr); if (m_mapCmd.isEmpty()) return; emit signal_command_finish(QFtp::Mkdir, smd.vParam, errstr); if (errstr.isEmpty()) { if (m_cmd == QC_MKD || m_cmd == QC_MKDS) inc_record(rt_success); } } void QFtpClient::rmd_result(const SingleCmd& smd, QString errstr) { if (m_mapCmd.isEmpty()) return; const QString strcmd = tr("rm dir"); if (!errstr.isEmpty()) { if (smd.vParam.size() > 0) { KOE_WARN(tr("Fail to %1:%2, for reason:%3").arg(strcmd).arg(smd.vParam[0].toString()).arg(errstr)); } } else { if (smd.vParam.size() > 0) { KOE_DEBUG(QString("%1:%2").arg(strcmd).arg(smd.vParam[0].toString())); } } emit signal_command_finish(QFtp::Rmdir, smd.vParam, errstr); #ifdef _DEBUG time_span(); #endif } void QFtpClient::rm_result(const SingleCmd& smd, QString errstr) { if (m_mapCmd.isEmpty()) return; const QString strcmd = tr("rm file"); if (!errstr.isEmpty()) { if (smd.vParam.size() > 0) { KOE_WARN(tr("fail to %1:%2, for reason:%3").arg(strcmd).arg(smd.vParam[0].toString()).arg(errstr)); if (m_cmd == QC_RM_FILE || m_cmd == QC_RM_TREE) inc_record(rt_success); } } else { if (smd.vParam.size() > 0) { KOE_DEBUG(QString("%1:%2").arg(strcmd).arg(smd.vParam[0].toString())); } } emit signal_command_finish(QFtp::Remove, smd.vParam, errstr); #ifdef _DEBUG time_span(); #endif } void QFtpClient::rename_result(const SingleCmd& smd, QString errstr) { if (m_mapCmd.isEmpty()) return; const QString strcmd = tr("rename"); if (!errstr.isEmpty()) { if (smd.vParam.size() > 2) { KOE_WARN(tr("fail to %1:%2 -> %3, for reason:%4").arg(strcmd).arg(smd.vParam[0].toString()).arg(smd.vParam[02].toString()).arg(errstr)); if (m_cmd == QC_RENAME) inc_record(rt_success); } } emit signal_command_finish(QFtp::Rename, smd.vParam, errstr); #ifdef _DEBUG time_span(); #endif } void QFtpClient::build_pwd_cd_cmd(const QString& dirname, bool done_list) { SingleCmd smd; smd.cmd = QFtp::Cd; smd.vParam.append(dirname); smd.vParam.append(done_list ? 1 : 0); m_lCmd.append(smd); } void QFtpClient::build_cd_cmd(const QString& remotepath) { build_cd_cmd(remotepath, m_lCmd); } void QFtpClient::build_cd_cmd(const QString& remotepath, QList<SingleCmd>& l) { QString sPath = remotepath; sPath = sPath.replace("\\", "/"); // "/" 替换 "\" if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/" QStringList v = sPath.split('/'); while (!v.isEmpty()) { QString itemback = v.back(); if (itemback.contains('.')) { v.pop_back(); // "/aa/bb/cc.py" -> "/aa/bb", 去除尾部含"."的文件名 if (itemback == "..") v.pop_back(); // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."的再进行一次上切 } else break; } SingleCmd smd; smd.cmd = QFtp::Cd; smd.vParam.append("/"); l.append(smd); for (const QString& s : v) { if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./" if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd" if (!l.isEmpty()) l.pop_back(); continue; } smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); l.append(smd); } } void QFtpClient::build_mkdir_cmd(const QString& remotepath) { QString sPath = remotepath; sPath = sPath.replace("\\", "/"); if (remotepath.contains('/')) { if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/" QStringList v = sPath.split('/'); if (!v.isEmpty() && v.front().isEmpty()) v.pop_front(); while (v.contains("..")) { // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."的再进行一次上切 int index = v.indexOf(".."); if (index >= 0) { v.removeAt(index); if(index > 0) v.removeAt(index - 1); } } if (v.isEmpty()) return; SingleCmd smd; smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd); for (const QString& s : v) { if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./" if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd" if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue; } smd.vParam.clear(); smd.cmd = QFtp::Mkdir; smd.vParam.append(s); m_lCmd.append(smd); smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd); } } else { SingleCmd smd; smd.cmd = QFtp::Mkdir; smd.vParam.append(sPath); m_lCmd.append(smd); } } void QFtpClient::build_rmdir_cmd(const QString& remotepath) { QString sPath = remotepath; sPath = sPath.replace("\\", "/"); SingleCmd smd; QString targetdir = remotepath; if (sPath.contains('/')) { if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/" QStringList v = sPath.split('/'); if (v.isEmpty()) { KOE_WARN(tr("giving param not directory:%1").arg(remotepath)); return; } while (!v.isEmpty()) { const QString& itemback = v.back(); if (itemback.contains('.')) { v.pop_back(); // "/aa/bb/cc.py" -> "/aa/bb", 去除尾部含"."的文件名 if (itemback == "..") v.pop_back(); // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."的再进行一次上切 } else break; } if (v.isEmpty()) return; targetdir = v.last(); smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.push_back(smd); for (const QString& s : v) { if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./" if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd" if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue; } smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.push_back(smd); } } else { sPath = pwd() + '/' + targetdir; smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(targetdir); m_lCmd.push_back(smd); } smd.vParam.clear(); smd.cmd = QFtp::List; smd.vParam.append(sPath); m_lCmd.append(smd); m_listcmd = QFtp::Command::Rmdir; QList<SingleCmd> cdcmd; build_cd_cmd(pwd(), cdcmd); smd.cmd = QFtp::Rmdir; smd.vParam.clear(); smd.vParam.append(targetdir); smd.vParam.append(pwd() + '/' + targetdir); cdcmd.append(smd); cdcmd.append(m_rmlist); m_rmlist = cdcmd; } void QFtpClient::build_rm_cmd(const QString& remotefile) { QString sPath = remotefile; sPath = sPath.replace("\\", "/"); SingleCmd smd; QString targetfile = remotefile; if (remotefile.contains('/')) { if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/" QStringList v = sPath.split('/'); while (!v.isEmpty()) { QString itemback = v.back(); if (itemback == "..") { // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."进行两次上切 v.pop_back(); v.pop_back(); } else break; } if (v.isEmpty()) return; targetfile = v.takeLast(); if (!targetfile.contains('.')) { KOE_WARN(tr("giving param not file:%1").arg(remotefile)); return; } smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd); for (const QString& s : v) { if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./" if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd" if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue; } smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd); } } else sPath = pwd(); smd.vParam.clear(); smd.cmd = QFtp::Remove; smd.vParam.append(targetfile); smd.vParam.append(sPath); m_lCmd.append(smd); } void QFtpClient::build_put_cmd(const QString& localfile, const QString& remotefile) { QString sLocalPath = localfile; sLocalPath = sLocalPath.replace('\\', '/'); QFileInfo qinfo(sLocalPath); if (!qinfo.exists()) { KOE_WARN(tr("local file not exist:%1").arg(localfile)); return; } if (!qinfo.isFile()) { KOE_WARN(tr("local file is not file:%1").arg(localfile)); return; } QString filename = sLocalPath.mid(sLocalPath.lastIndexOf('/') + 1), sRemotePath = remotefile.isEmpty() ? pwd() + '/' + filename : remotefile; sRemotePath = sRemotePath.replace('\\', '/'); QStringList v = sRemotePath.split("/"); if (!remotefile.isEmpty()) { // 上传文件名不可以是 "." 或 ".." if (v.isEmpty() || v.back() == ".." || v.back() == ".") { KOE_WARN(tr("param error")); return; } // remotefile以"/"结尾, 表示上传文件未指定文件名, 则使用本地文件名, example: // localfile -> E:/dd/ee/ff.xx // remotefile -> /aa/bb/cc/ // final remotefile -> /aa/bb/cc/ff.xx filename = v.back().isEmpty() ? sLocalPath.mid(sLocalPath.lastIndexOf('/') + 1) : v.takeLast(); build_mkdir_cmd(v.join('/')); } SingleCmd smd; smd.cmd = QFtp::Put; smd.vParam.append(localfile); smd.vParam.append(filename); smd.vParam.append(sRemotePath); m_lCmd.append(smd); } void QFtpClient::build_puts_cmd(const QVariantList& files) { int file_size = files.size() / 2; for (int i = 0; i < file_size; ++i) { QString slocal = files[2 * i].toString(), sremote = files[2 * i + 1].toString(); sremote = sremote.replace('\\', '/'); QStringList v = sremote.split("/"); // 上传文件名不可以是 "." 或 ".." if (v.isEmpty() || v.back() == ".." || v.back() == ".") { KOE_WARN(tr("param error")); continue; } QString remotefilename = v.back().isEmpty() ? slocal.mid(slocal.lastIndexOf('/') + 1) : v.takeLast(); build_mkdir_cmd(v.join('/')); SingleCmd smd; smd.cmd = QFtp::Put; smd.vParam.append(slocal); smd.vParam.append(remotefilename); smd.vParam.append(sremote); m_lCmd.append(smd); } } void QFtpClient::build_putree_cmd(const QString& localpath, const QString& remotepath, const QStringList& vExcept) { QString sRemotePath = remotepath; sRemotePath = sRemotePath.replace('\\', '/'); //rmdir(sRemotePath); // if need rm ? QDir qLocalParentDir(localpath); if (!qLocalParentDir.exists()) { KOE_WARN(tr("local path not exist:%1").arg(qLocalParentDir.path())); return; } QFileInfoList vFileInfo = qLocalParentDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::DirsLast); if (vFileInfo.isEmpty()) { // there is no file in this dir, only mkdir if (sRemotePath.split("/").isEmpty()) { KOE_WARN(tr("param error")); return; } if (!in_stringlist(sRemotePath, vExcept)) build_mkdir_cmd(sRemotePath); } else { for (const QFileInfo& FileInfo : vFileInfo) { QString sFileName = FileInfo.fileName(); if (FileInfo.isDir()) { // 子对象是目录, 则递归上传目录 qLocalParentDir.cd(sFileName); if (!in_stringlist(qLocalParentDir.path(), vExcept)) build_putree_cmd(qLocalParentDir.path(), sRemotePath.endsWith("/") ? sRemotePath + sFileName : sRemotePath + "/" + sFileName, vExcept); qLocalParentDir.cdUp(); } else if (FileInfo.isFile()) { // 子对象是文件, 则上传单个文件 if (!in_stringlist(qLocalParentDir.path() + "/" + sFileName, vExcept)) { build_put_cmd(qLocalParentDir.path() + "/" + sFileName, sRemotePath.endsWith("/") ? sRemotePath + sFileName : sRemotePath + "/" + sFileName); inc_record(rt_total); } } } } } void QFtpClient::build_get_buffer_cmd(const QString& remotefile) { QString sRemotePath = remotefile; sRemotePath = sRemotePath.replace('\\', '/'); QStringList v = sRemotePath.split("/"); if (v.isEmpty()) { KOE_WARN(tr("param error")); return; } build_cd_cmd(sRemotePath); QString remotefilename = v.takeLast(); SingleCmd smd; smd.cmd = QFtp::Get; smd.vParam.append(sRemotePath); smd.vParam.append(remotefilename); m_lCmd.append(smd); } void QFtpClient::build_get_cmd(const QString& remotefile, const QString& localfile) { QString sRemotePath = remotefile; sRemotePath = sRemotePath.replace('\\', '/'); QString filename = sRemotePath; if (remotefile.contains('/')) { QStringList v = sRemotePath.split("/"); if (v.isEmpty()) { KOE_WARN(tr("param error")); return; } build_cd_cmd(sRemotePath); filename = v.takeLast(); SingleCmd smd; smd.cmd = QFtp::Get; smd.vParam.append(sRemotePath); smd.vParam.append(filename); smd.vParam.append(localfile); m_lCmd.append(smd); } else { SingleCmd smd; smd.cmd = QFtp::Get; smd.vParam.append(pwd()); smd.vParam.append(filename); smd.vParam.append(localfile.endsWith('/') ? localfile + filename : localfile); m_lCmd.append(smd); } } void QFtpClient::build_gets_cmd(const QVariantList& files) { int file_size = files.size() / 2; for (int i = 0; i < file_size; ++i) { QString sremote = files[2 * i].toString(), slocal = files[2 * i + 1].toString(); sremote = sremote.replace('\\', '/'); QStringList v = sremote.split("/"); if (v.isEmpty()) { KOE_WARN(tr("param error")); continue; } build_cd_cmd(sremote); QString remotefilename = v.takeLast(); SingleCmd smd; smd.cmd = QFtp::Get; smd.vParam.append(sremote); smd.vParam.append(remotefilename); smd.vParam.append(slocal); m_lCmd.append(smd); } } void QFtpClient::build_getree_cmd(const QString& remotepath, const QString& localpath, const QStringList& vExcept) { m_CurrentPath = qMakePair(localpath, remotepath); build_cd_cmd(remotepath); // 进入远程目录后 list 检索文件, list 后续操作中执行 get command SingleCmd smd; smd.cmd = QFtp::List; m_lCmd.append(smd); m_listcmd = QFtp::Command::Get; m_vExcept.unite(vExcept.toSet()); } void QFtpClient::build_rename_cmd(const QString& remotefilepath, const QString& newname) { QString sPath = remotefilepath; sPath = sPath.replace('\\', '/'); SingleCmd smd; QString target = remotefilepath; if (remotefilepath.contains('/')) { QStringList v = sPath.split("/"); target = v.takeLast(); if (target.isEmpty()) return; smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd); for (const QString& s : v) { if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./" if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd" if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue; } smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd); } } else sPath = pwd(); smd.vParam.clear(); smd.cmd = QFtp::Rename; smd.vParam.append(sPath); smd.vParam.append(target); smd.vParam.append(newname); m_lCmd.append(smd); } void QFtpClient::build_list_cmd(const QString& remotepath) { SingleCmd smd; if (!remotepath.isEmpty()) { QString sPath = remotepath; sPath = sPath.replace('\\', '/'); QStringList v = sPath.split("/"); smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd); for (const QString& s : v) { if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./" if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd" if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue; } smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd); } } smd.vParam.clear(); smd.cmd = QFtp::List; m_lCmd.append(smd); m_listcmd = QFtp::Command::List; } void QFtpClient::get_result(const SingleCmd& smd, QString errstr) { if (m_mapCmd.isEmpty()) return; QVariantList v = smd.vParam; if (v.size() < 2) return; QString remotefilepath = v[0].toString(), remotefilename = v[1].toString(); if (v.size() > 2) { QString localfilepath = v[2].toString(); QFile* pFile = v.size() == 4 ? v.takeLast().value<QFile*>() : 0; // there is a question here: if command "get" not come back, memory will leak, maybe it can be controlled by timer if (pFile) { if (pFile->isOpen()) pFile->close(); delete pFile; } if (errstr.isEmpty()) { KOE_DEBUG(tr("download file:%1 -> %2").arg(remotefilepath).arg(localfilepath)); if (m_cmd == QC_GET_BUFFER || m_cmd == QC_GET_FILE || m_cmd == QC_GET_FILES || m_cmd == QC_GET_TREE) inc_record(rt_success); } else { KOE_WARN(tr("Fail to download:%1 -> %2, for reason:%3").arg(remotefilepath).arg(localfilepath).arg(errstr)); QDir().remove(localfilepath); } } else if (m_buffer) emit signal_get_buffer(m_buffer->buffer()); emit signal_command_finish(QFtp::Get, v, errstr); #ifdef _DEBUG time_span(); #endif } void QFtpClient::clear_cmd() { m_CurrentPath = qMakePair(QString(), QString()); m_PendingPath.clear(); m_lCmd.clear(); m_mapCmd.clear(); m_listcmd = QFtp::Command::None; } void QFtpClient::reset_record() { total_count = 0; execute_count = 0; success_count = 0; } void QFtpClient::inc_record(record_type ty, int val) { switch (ty) { case rt_success: success_count += val; break; case rt_executing: execute_count += val; break; case rt_total: total_count += val; break; default: break; } } bool QFtpClient::inner_put_file(const QString& localabsfile, const QString& remoteabsfile, int msec) { if (localabsfile.isEmpty() || remoteabsfile.isEmpty()) return false; const QString strcmd = tr("put file"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Put, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); QFileInfo qlocalfile(localabsfile); if (!qlocalfile.exists()) { KOE_WARN(tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(localabsfile)); emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(localabsfile)); return false; } #ifdef _DEBUG set_start(); #endif m_cmd = QC_PUT_FILE; reset_record(); inc_record(rt_total); build_put_cmd(localabsfile, remoteabsfile); return next_cmd_util_done(msec); } bool QFtpClient::inner_put_files(QVariantList& files, int msec) { if(files.isEmpty()) return false; const QString strcmd = tr("put file"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Put, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); int file_size = files.size() / 2; if(file_size <= 0) return false; for (int i = file_size - 1; i >= 0; --i) { QFileInfo qlocalfile(files[2*i].toString()); if (!qlocalfile.exists()) { KOE_WARN(tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(files[2 * i].toString())); emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(files[2 * i].toString())); files.removeAt(2 * i); files.removeAt(2 * i + 1); continue; } } clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_PUT_FILES; reset_record(); inc_record(rt_total, file_size); build_puts_cmd(files); return next_cmd_util_done(msec); } bool QFtpClient::inner_put_tree(const QString& localabspath, const QString& remoteabspath, const QStringList& vExcept, int msec) { if (localabspath.isEmpty() || remoteabspath.isEmpty()) return false; const QString strcmd = tr("put tree"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Put, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); QDir qLocalParentDir(localabspath); if (!qLocalParentDir.exists()) { KOE_WARN(tr("fail to %1, local path not exist:%2").arg(strcmd).arg(localabspath)); emit signal_command_finish(QFtp::Put, {}, tr("fail to %1, local path not exist:%2").arg(strcmd).arg(localabspath)); return false; } clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_PUT_TREE; reset_record(); build_putree_cmd(localabspath, remoteabspath, vExcept); return next_cmd_util_done(msec); } bool QFtpClient::inner_get_buffer(const QString& remoteabsfile, int msec) { if (remoteabsfile.isEmpty()) return false; const QString strcmd = tr("get file"); if (state() != QFtp::LoggedIn) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_GET_BUFFER; reset_record(); inc_record(rt_total); build_get_buffer_cmd(remoteabsfile); return next_cmd_util_done(msec); } bool QFtpClient::inner_get_file(const QString& remotefile, const QString& localfile, int msec){ if(remotefile.isEmpty() || localfile.isEmpty()) return false; const QString strcmd = tr("get file"); if (state() != QFtp::LoggedIn) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); QDir qLocalDir(localfile.mid(0, localfile.lastIndexOf("/"))); if (!qLocalDir.exists()) QDir().mkpath(qLocalDir.path()); #ifdef _DEBUG set_start(); #endif m_cmd = QC_GET_FILE; reset_record(); inc_record(rt_total); build_get_cmd(remotefile, localfile); return next_cmd_util_done(msec); } bool QFtpClient::inner_get_files(QVariantList& files, int msec) { if(files.isEmpty()) return false; const QString strcmd = tr("get file"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); int file_size = files.size() / 2; if(file_size <= 0) return false; clear_cmd(); for (int i = 0; i < file_size; ++i) { QFileInfo qremotefile(files[2 * i].toString()), qlocalfile(files[2 * i + 1].toString()); QDir qLocalDir(qlocalfile.absolutePath().mid(0, qlocalfile.absolutePath().lastIndexOf("/"))); if (!qLocalDir.exists()) QDir().mkpath(qLocalDir.path()); } #ifdef _DEBUG set_start(); #endif m_cmd = QC_GET_FILES; reset_record(); inc_record(rt_total, file_size); build_gets_cmd(files); return next_cmd_util_done(msec); } bool QFtpClient::inner_get_tree(const QString& remoteabspath, const QString& localabspath, const QStringList& vExcept, int msec){ if(remoteabspath.isEmpty() || localabspath.isEmpty()) return false; const QString strcmd = tr("get tree"); if (state() != QFtp::LoggedIn) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_vExcept.clear(); m_cmd = QC_GET_TREE; reset_record(); build_getree_cmd(remoteabspath, localabspath, vExcept); return next_cmd_util_done(msec); } bool QFtpClient::inner_rm_file(const QString& remotefile, int msec){ if(remotefile.isEmpty()) return false; const QString strcmd = tr("rm file"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Remove, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Remove, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_RM_FILE; reset_record(); inc_record(rt_total); build_rm_cmd(remotefile); return next_cmd_util_done(msec); } bool QFtpClient::inner_rm_tree(const QString& dir, int msec){ if(dir.isEmpty()) return false; const QString strcmd = tr("rm tree"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Rmdir, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Rmdir, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_RM_TREE; reset_record(); m_rmlist.clear(); build_rmdir_cmd(dir); return next_cmd_util_done(msec); } bool QFtpClient::inner_mk_dir(const QString& dir, int msec){ if(dir.isEmpty()) return false; const QString strcmd = tr("mk dir"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_MKD; reset_record(); inc_record(rt_total); build_mkdir_cmd(dir.indexOf(".") >= 0 ? dir.left(dir.lastIndexOf("/")) : dir); return next_cmd_util_done(msec); } bool QFtpClient::inner_mk_dir(const QStringList& dirlist, int msec){ if(dirlist.isEmpty()) return false; const QString strcmd = tr("mk multi dir"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_MKDS; reset_record(); inc_record(rt_total, dirlist.size()); for (const QString& remotedir : dirlist) build_mkdir_cmd(remotedir.indexOf(".") >= 0 ? remotedir.left(remotedir.lastIndexOf("/")) : remotedir); return next_cmd_util_done(msec); } bool QFtpClient::inner_rename(const QString& remotefilepath, const QString& newname, int msec){ if(remotefilepath.isEmpty() || newname.isEmpty()) return false; const QString strcmd = tr("rename"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Rename, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Rename, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_RENAME; reset_record(); inc_record(rt_total); build_rename_cmd(remotefilepath, newname); return next_cmd_util_done(msec); } bool QFtpClient::inner_list(const QString& remotepath, int msec) { if(remotepath.isEmpty()) return false; const QString strcmd = tr("list"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::List, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::List, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_cmd = QC_LIST; reset_record(); inc_record(rt_total); m_listresult.clear(); build_list_cmd(remotepath); return next_cmd_util_done(msec); } bool QFtpClient::inner_cd(const QString& dirname, bool done_list, int msec) { if(dirname.isEmpty()) return false; const QString strcmd = tr("cd"); if (!is_connect()) { KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); emit signal_command_finish(QFtp::Cd, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd)); return false; } if (has_cmd()) { KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); emit signal_command_finish(QFtp::Cd, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd)); return false; } else KOE_DEBUG(tr("command: %1").arg(strcmd)); clear_cmd(); #ifdef _DEBUG set_start(); #endif m_listresult.clear(); m_cmd = QC_CD; reset_record(); inc_record(rt_total); build_pwd_cd_cmd(dirname, done_list); return next_cmd_util_done(msec); } 这是QFtpclient.cpp
07-11
a 0:00:00 Installing build dependencies ... error error: subprocess-exited-with-error × pip subprocess to install build dependencies did not run successfully. │ exit code: 1 ╰─> [229 lines of output] WARNING: Skip installing pip, this will break the python-pip package (termux). Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Ignoring numpy: markers 'python_version == "3.6" and platform_machine != "aarch64" and platform_machine != "arm64"' don't match your environment Ignoring numpy: markers 'python_version == "3.7" and platform_machine != "aarch64" and platform_machine != "arm64"' don't match your environment Ignoring numpy: markers 'python_version == "3.8" and platform_machine != "aarch64" and platform_machine != "arm64"' don't match your environment Ignoring numpy: markers 'python_version < "3.9" and sys_platform == "linux" and platform_machine == "aarch64"' don't match your environment Ignoring numpy: markers 'python_version < "3.9" and sys_platform == "darwin" and platform_machine == "arm64"' don't match your environment Ignoring setuptools: markers 'python_version < "3.12"' don't match your environment Collecting numpy>=2.0.0 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/2e/19/d7c972dfe90a353dbd3efbbe1d14a5951de80c99c9dc1b93cd998d51dc0f/numpy-2.3.1.tar.gz (20.4 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 20.4/20.4 MB 8.5 MB/s eta 0:00:00 Installing build dependencies: started Installing build dependencies: finished with status 'done' Getting requirements to build wheel: started Getting requirements to build wheel: finished with status 'done' Installing backend dependencies: started Installing backend dependencies: still running... Installing backend dependencies: finished with status 'error' error: subprocess-exited-with-error × pip subprocess to install backend dependencies did not run successfully. │ exit code: 1 ╰─> [196 lines of output] Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting ninja>=1.8.2 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/95/d4/6b0324541018561c5e73e617bd16f20a4fc17d1179bb3b3520b6ca8beb7b/ninja-1.11.1.4.tar.gz (201 kB) Installing build dependencies: started Installing build dependencies: finished with status 'done' Getting requirements to build wheel: started Getting requirements to build wheel: finished with status 'done' Installing backend dependencies: started Installing backend dependencies: finished with status 'done' Preparing metadata (pyproject.toml): started Preparing metadata (pyproject.toml): finished with status 'done' Collecting patchelf>=0.11.0 Downloading https://pypi.tuna.tsinghua.edu.cn/packages/0d/41/dc3ee5838db2d90be935adb53ae7745135d9c719d070b1989b246f983c7f/patchelf-0.17.2.2.tar.gz (149 kB) Installing build dependencies: started Installing build dependencies: finished with status 'done' Getting requirements to build wheel: started Getting requirements to build wheel: finished with status 'done' Installing backend dependencies: started Installing backend dependencies: finished with status 'done' Preparing metadata (pyproject.toml): started Preparing metadata (pyproject.toml): finished with status 'done' Building wheels for collected packages: ninja, patchelf Building wheel for ninja (pyproject.toml): started Building wheel for ninja (pyproject.toml): still running... Building wheel for ninja (pyproject.toml): finished with status 'error' error: subprocess-exited-with-error × Building wheel for ninja (pyproject.toml) did not run successfully. │ exit code: 1 ╰─> [120 lines of output] /data/data/com.termux/files/usr/tmp/pip-build-env-4j78z2m7/normal/lib/python3.12/site-packages/setuptools_scm/git.py:310: UserWarning: git archive did not support describe output warnings.warn("git archive did not support describe output") /data/data/com.termux/files/usr/tmp/pip-build-env-4j78z2m7/normal/lib/python3.12/site-packages/setuptools_scm/git.py:328: UserWarning: unprocessed git archival found (no export subst applied) warnings.warn("unprocessed git archival found (no export subst applied)") *** scikit-build-core 0.11.5 using CMake 3.31.6 (wheel) *** Configuring CMake... loading initial cache file build/py3-none-linux_aarch64/CMakeInit.txt -- The C compiler identification is Clang 20.1.7 -- The CXX compiler identification is Clang 20.1.7 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /data/data/com.termux/files/usr/bin/aarch64-linux-android-clang - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /data/data/com.termux/files/usr/bin/aarch64-linux-android-clang++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- ************************************ -- Ninja Python Distribution -- -- RUN_NINJA_TEST : OFF -- ************************************ -- IPO / LTO not supported: <Change Dir: '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' Run Build Command(s): /data/data/com.termux/files/usr/bin/cmake -E env VERBOSE=1 /data/data/com.termux/files/usr/bin/make -f Makefile /data/data/com.termux/files/usr/bin/cmake -S/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/src -B/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin --check-build-system CMakeFiles/Makefile.cmake 0 /data/data/com.termux/files/usr/bin/cmake -E cmake_progress_start /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin/CMakeFiles /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin//CMakeFiles/progress.marks /data/data/com.termux/files/usr/bin/make -f CMakeFiles/Makefile2 all make[1]: Entering directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' /data/data/com.termux/files/usr/bin/make -f CMakeFiles/foo.dir/build.make CMakeFiles/foo.dir/depend make[2]: Entering directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' cd /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin && /data/data/com.termux/files/usr/bin/cmake -E cmake_depends "Unix Makefiles" /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/src /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/src /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin/CMakeFiles/foo.dir/DependInfo.cmake make[2]: Leaving directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' /data/data/com.termux/files/usr/bin/make -f CMakeFiles/foo.dir/build.make CMakeFiles/foo.dir/build make[2]: Entering directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' [ 25%] Building CXX object CMakeFiles/foo.dir/foo.cpp.o /data/data/com.termux/files/usr/bin/aarch64-linux-android-clang++ -O2 -g -DNDEBUG -flto=thin -MD -MT CMakeFiles/foo.dir/foo.cpp.o -MF CMakeFiles/foo.dir/foo.cpp.o.d -o CMakeFiles/foo.dir/foo.cpp.o -c /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/src/foo.cpp [ 50%] Linking CXX static library libfoo.a /data/data/com.termux/files/usr/bin/cmake -P CMakeFiles/foo.dir/cmake_clean_target.cmake /data/data/com.termux/files/usr/bin/cmake -E cmake_link_script CMakeFiles/foo.dir/link.txt --verbose=1 "/data/data/com.termux/files/usr/bin/llvm-ar" qc libfoo.a CMakeFiles/foo.dir/foo.cpp.o "/data/data/com.termux/files/usr/bin/llvm-ranlib" libfoo.a make[2]: Leaving directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' [ 50%] Built target foo /data/data/com.termux/files/usr/bin/make -f CMakeFiles/boo.dir/build.make CMakeFiles/boo.dir/depend make[2]: Entering directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' cd /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin && /data/data/com.termux/files/usr/bin/cmake -E cmake_depends "Unix Makefiles" /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/src /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/src /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin/CMakeFiles/boo.dir/DependInfo.cmake make[2]: Leaving directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' /data/data/com.termux/files/usr/bin/make -f CMakeFiles/boo.dir/build.make CMakeFiles/boo.dir/build make[2]: Entering directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' [ 75%] Building CXX object CMakeFiles/boo.dir/main.cpp.o /data/data/com.termux/files/usr/bin/aarch64-linux-android-clang++ -O2 -g -DNDEBUG -flto=thin -MD -MT CMakeFiles/boo.dir/main.cpp.o -MF CMakeFiles/boo.dir/main.cpp.o.d -o CMakeFiles/boo.dir/main.cpp.o -c /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/src/main.cpp [100%] Linking CXX executable boo /data/data/com.termux/files/usr/bin/cmake -E cmake_link_script CMakeFiles/boo.dir/link.txt --verbose=1 aarch64-linux-android-clang++: error: invalid linker name in argument '-fuse-ld=gold' aarch64-linux-android-clang++: error: invalid linker name in argument '-fuse-ld=gold' /data/data/com.termux/files/usr/bin/aarch64-linux-android-clang++ -O2 -g -DNDEBUG -flto=thin -fuse-ld=gold CMakeFiles/boo.dir/main.cpp.o -o boo libfoo.a make[2]: *** [CMakeFiles/boo.dir/build.make:104: boo] Error 1 make[2]: Leaving directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' make[1]: *** [CMakeFiles/Makefile2:125: CMakeFiles/boo.dir/all] Error 2 make[1]: Leaving directory '/data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64/_deps/ninja-build/CMakeFiles/_CMakeLTOTest-CXX/bin' make: *** [Makefile:94: all] Error 2 > -- Performing Test flag_no_deprecated -- Performing Test flag_no_deprecated - Success -- Performing Test flag_color_diag -- Performing Test flag_color_diag - Success CMake Warning at ninja-upstream/CMakeLists.txt:49 (message): re2c was not found; changes to src/*.in.cc will not affect your build. -- Looking for fork -- Looking for fork - found -- Looking for pipe -- Looking for pipe - found -- Configuring done (9.0s) -- Generating done (0.1s) -- Build files have been written to: /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/build/py3-none-linux_aarch64 *** Building project with Unix Makefiles... [ 1%] Building CXX object _deps/ninja-build/CMakeFiles/libninja-re2c.dir/src/depfile_parser.cc.o [ 2%] Building CXX object _deps/ninja-build/CMakeFiles/libninja-re2c.dir/src/lexer.cc.o [ 2%] Built target libninja-re2c [ 4%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/build_log.cc.o [ 5%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/build.cc.o [ 7%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/clean.cc.o [ 8%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/clparser.cc.o [ 10%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/dyndep.cc.o [ 11%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/dyndep_parser.cc.o [ 13%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/debug_flags.cc.o [ 14%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/deps_log.cc.o [ 16%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/disk_interface.cc.o [ 17%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/edit_distance.cc.o [ 19%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/eval_env.cc.o [ 20%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/graph.cc.o [ 22%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/graphviz.cc.o [ 23%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/json.cc.o [ 25%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/line_printer.cc.o [ 26%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/manifest_parser.cc.o [ 28%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/metrics.cc.o [ 29%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/missing_deps.cc.o [ 31%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/parser.cc.o [ 32%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/state.cc.o [ 34%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/status.cc.o [ 35%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/string_piece_util.cc.o [ 37%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/tokenpool-gnu-make.cc.o [ 38%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/util.cc.o [ 40%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/version.cc.o [ 41%] Building CXX object _deps/ninja-build/CMakeFiles/libninja.dir/src/subprocess-posix.cc.o /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/ninja_7200d3032e2b456abb23067d29afe294/ninja-upstream/src/subprocess-posix.cc:26:10: fatal error: 'spawn.h' file not found 26 | #include <spawn.h> | ^~~~~~~~~ 1 error generated. make[2]: *** [_deps/ninja-build/CMakeFiles/libninja.dir/build.make:429: _deps/ninja-build/CMakeFiles/libninja.dir/src/subprocess-posix.cc.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:193: _deps/ninja-build/CMakeFiles/libninja.dir/all] Error 2 make: *** [Makefile:136: all] Error 2 *** CMake build failed [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed building wheel for ninja Building wheel for patchelf (pyproject.toml): started Building wheel for patchelf (pyproject.toml): finished with status 'error' error: subprocess-exited-with-error × Building wheel for patchelf (pyproject.toml) did not run successfully. │ exit code: 1 ╰─> [29 lines of output] *** scikit-build-core 0.11.5 using CMake 3.31.6 (wheel) *** Configuring CMake... loading initial cache file build/py3-none-linux_aarch64/CMakeInit.txt -- The C compiler identification is Clang 20.1.7 -- The CXX compiler identification is Clang 20.1.7 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /data/data/com.termux/files/usr/bin/aarch64-linux-android-clang - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /data/data/com.termux/files/usr/bin/aarch64-linux-android-clang++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (2.6s) -- Generating done (0.0s) -- Build files have been written to: /data/data/com.termux/files/usr/tmp/pip-install-nuu7do6s/patchelf_96e1be08ef43472d93a934bd092c3537/build/py3-none-linux_aarch64 *** Building project with Unix Makefiles... [ 12%] Creating directories for 'build_patchelf' [ 25%] No download step for 'build_patchelf' [ 37%] No update step for 'build_patchelf' [ 50%] Performing patch step for 'build_patchelf' ./bootstrap.sh: 2: autoreconf: not found make[2]: *** [CMakeFiles/build_patchelf.dir/build.make:114: build_patchelf-prefix/src/build_patchelf-stamp/build_patchelf-patch] Error 127 make[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/build_patchelf.dir/all] Error 2 make: *** [Makefile:136: all] Error 2 *** CMake build failed [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. ERROR: Failed building wheel for patchelf Failed to build ninja patchelf ERROR: Failed to build installable wheels for some pyproject.toml based projects (ninja, patchelf) [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. error: subprocess-exited-with-error × pip subprocess to install backend dependencies did not run successfully. │ exit code: 1 ╰─> See above for output. note: This error originates from a subprocess, and is likely not a problem with pip. [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. error: subprocess-exited-with-error × pip subprocess to install build dependencies did not run successfully. │ exit code: 1 ╰─> See above for output. note: This error originates from a subprocess, and is likely not a problem with pip. ~ $
07-01
#ifndef __QFTP_CLIENT_H__ #define __QFTP_CLIENT_H__ // make sure to add qftp depending on #include <QTimer> #include <QFile> #include <QUrl> #include <QMap> #include <QVariant> #include <QMutex> #include <QBuffer> #include <QSet> #include "qftp.h" struct RemoteDir; struct SingleCmd; class QFtpClient : public QFtp { Q_OBJECT public: enum QFTP_CMD { QC_NONE, QC_CD, QC_LIST, QC_RENAME, QC_PUT_FILE, QC_PUT_FILES, QC_PUT_TREE, QC_GET_BUFFER, QC_GET_FILE, QC_GET_FILES, QC_GET_TREE, QC_RM_FILE, QC_RM_TREE, QC_MKD, QC_MKDS, }; enum record_type { rt_success, rt_executing, rt_total, rt_count, }; public: QFtpClient(QString serverip = "", QString username = "", QString password = "", qint16 port = 21, QObject* parent = 0); ~QFtpClient(); void setIP(const QString& ip, const qint16 port = 21); void setUser(const QString& username, const QString& password); void close_host(); bool sync_connect(int msec = 3000); // 现存缺陷: 不能创建含中文的目录/文件 // 绝对路径操作接口 // 上传文件/目录 bool put_files(const QList< QPair<QString, QString> >& vfiles, int msec = 30000); //list< pir<localfile, remotefile> > bool put_file(const QString& localabsfile, const QString& remoteabsfile, int msec = 3000); bool put_tree(const QString& localabspath, const QString& remoteabspath, const QStringList& exceptabspath = {}, int msec = 30000); // 下载文件/目录 bool get_buffer(const QString& remoteabsfile, int msec = 3000); bool get_file(const QString& remoteabsfile, const QString& localabsfile, int msec = 3000); bool get_files(const QList< QPair<QString, QString> >& vfiles, int msec = 30000); //list< pir<remotefile, localfile> > bool get_tree(const QString& remoteabspath, const QString& localabspath, const QStringList& exceptabspath = {}, int msec = 30000); // 删除文件/目录 bool rm_file(const QString& remotefile, int msec = 3000); bool rm_tree(const QString& dir, int msec = 30000); // 新建目录 bool mk_dir(const QString& dir, int msec = 3000); bool mk_dir(const QStringList& dirlist, int msec = 3000); // 重命名 bool _rename(const QString& remotefilepath, const QString& newname, int msec = 3000); // 显示列表 bool _list(const QString& remotepath, int msec = 3000); // 当前目录操作接口 bool pwd_put_file(const QString& localabsfile, int msec = 3000); bool pwd_get_file(const QString& remotefile, const QUrl& localurl, int msec = 3000); bool pwd_rm_file(const QString& remotefile, int msec = 3000); bool pwd_rm_tree(const QString& remotedir, int msec = 10000); bool pwd_mk_dir(const QString& remotedir, int msec = 3000); bool pwd_rename(const QString& remotefile, const QString& newname, int msec = 3000); bool pwd_list(int msec = 3000); bool pwd_cd(const QString& dirname, bool done_list = false, int msec = 3000); // 是否被占用 bool is_busy()const; // 是否已连接 bool is_connect()const; QString pwd(); signals: void signal_state_changed(int); void signal_command_finish(int cmdid, QVariantList params, QString errorstring = ""); void signal_ftp_log(const QString&, bool error = false); void signal_list(const QList<QUrlInfo>&); void signal_get_buffer(const QByteArray&); void signal_done(int cmdid, int ok_num, int exec_num, int total_num); private: bool inner_put_file(const QString& localabsfile, const QString& remoteabsfile, int msec = 3000); bool inner_put_files(QVariantList& files, int msec = 30000); bool inner_put_tree(const QString& localabspath, const QString& remoteabspath, const QStringList& vExcept = {}, int msec = 30000); bool inner_get_buffer(const QString& remoteabsfile, int msec = 3000); bool inner_get_file(const QString& remoteabsfile, const QString& localabsfile, int msec = 3000); bool inner_get_files(QVariantList& files, int msec = 30000); bool inner_get_tree(const QString& remoteabspath, const QString& localabspath, const QStringList& vExcept = {}, int msec = 30000); bool inner_rm_file(const QString& remotefile, int msec = 3000); bool inner_rm_tree(const QString& dir, int msec = 30000); bool inner_mk_dir(const QString& dir, int msec = 3000); bool inner_mk_dir(const QStringList& dirlist, int msec = 3000); bool inner_rename(const QString& remotefilepath, const QString& newname, int msec = 3000); bool inner_list(const QString& remotepath = "", int msec = 3000); bool inner_cd(const QString& dirname, bool done_list = false, int msec = 3000); // done_list - 切换完成后, 是否需要list(用于ui显示) void connect_host(); void connect_result(QString errstr); void login_result(QString errstr); void close_result(QString errstr); void list_result(const SingleCmd& smd); void get_result(const SingleCmd& smd, QString errstr); bool has_cmd(); bool next_cmd(); bool next_cmd_util_done(int msec); void cd_result(const SingleCmd& smd, QString errstr); void put_result(const SingleCmd& smd, QString errstr); void mkd_result(const SingleCmd& smd, QString errstr); void rmd_result(const SingleCmd& smd, QString errstr); void rm_result(const SingleCmd& smd, QString errstr); void rename_result(const SingleCmd& smd, QString errstr); void build_pwd_cd_cmd(const QString& dirname, bool done_list = false); // 当前目录cd void build_cd_cmd(const QString& remotepath); // 绝对路径cd void build_cd_cmd(const QString& remotepath, QList<SingleCmd>& l); void build_mkdir_cmd(const QString& remotepath); void build_rmdir_cmd(const QString& remotepath); void build_rm_cmd(const QString& remotepath); void build_put_cmd(const QString& localfile, const QString& remotefile); void build_puts_cmd(const QVariantList&); void build_putree_cmd(const QString& localpath, const QString& remotepath, const QStringList& vExcept = {}); void build_get_buffer_cmd(const QString& remotefile); void build_get_cmd(const QString& remotefile, const QString& localfile); void build_gets_cmd(const QVariantList&); void build_getree_cmd(const QString& remotepath, const QString& localpath, const QStringList& vExcept = {}); void build_rename_cmd(const QString& remotefilepath, const QString& newname); void build_list_cmd(const QString& remotepath); void clear_cmd(); void reset_record(); void inc_record(record_type, int = 1); private slots: void slot_state_changed(int); void slot_timer_connect(); void slot_finish(int, bool); void slot_listinfo(const QUrlInfo&); void slot_inner_cmd(int cmdid, QVariantList params, QString errorstring); protected: QUrl m_url; QTimer* m_pConnect = Q_NULLPTR; QPair<QString, QString> m_CurrentPath; // local/remote path // download member QList< QPair<QString, QString> > m_PendingPath; // local/remote path QBuffer* m_buffer = 0; // rmdir member QList<SingleCmd> m_rmlist; // cmd member QList<SingleCmd> m_lCmd; QMap<int, SingleCmd> m_mapCmd; // list member QFtp::Command m_listcmd = QFtp::Command::None; QFtp::Command m_prevlistcmd = QFtp::Command::None; QList<QUrlInfo> m_listresult; QStringList m_PathSection = {}; QFTP_CMD m_cmd = QC_NONE; int success_count = 0, execute_count = 0, total_count = 0; QSet<QString> m_vExcept; }; #endif 这是QFtpclient.h
最新发布
07-11
/**************************************************************************** ** ** This file is part of the LibreCAD project, a 2D CAD program ** ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl) ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. ** ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file gpl-2.0.txt included in the ** packaging of this file. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** This copyright notice MUST APPEAR in all copies of the script! ** **********************************************************************/ #ifndef QC_APPLICATIONWINDOW_H #define QC_APPLICATIONWINDOW_H #undef QT_NO_WORKSPACE #include <qworkspace.h> #include "qc_mdiwindow.h" #include "qg_mainwindowinterface.h" #ifdef RS_SCRIPTING #include "qs_scripter.h" #include <qsproject.h> #endif class QG_LibraryWidget; class QG_CadToolBar; class QC_DialogFactory; class QG_LayerWidget; class QG_BlockWidget; class QG_CommandWidget; class QG_CoordinateWidget; class QG_MouseWidget; class QG_SelectionWidget; class QG_RecentFiles; class QG_PenToolBar; class QHelpEngine; class QC_PluginInterface; /** * Main application window. Hold together document, view and controls. * * @author Andrew Mustun */ class QC_ApplicationWindow: public QMainWindow, public QG_MainWindowInterface { Q_OBJECT public: QC_ApplicationWindow(); ~QC_ApplicationWindow(); void initActions(); void initMenuBar(); void initToolBar(); void initStatusBar(); void initSettings(); void restoreDocks(); void storeSettings(); void updateRecentFilesMenu(); void initMDI(); void initView(); bool queryExit(bool force); /** Catch hotkey for giving focus to command line. */ virtual void keyPressEvent(QKeyEvent* e); virtual void keyReleaseEvent(QKeyEvent* e); public slots: virtual void show(); void finishSplashScreen(); void slotFocus(); void slotBack(); void slotKillAllActions(); //void slotNext(); void slotEnter(); void slotFocusCommandLine(); void slotError(const QString& msg); void slotWindowActivated(QWidget* w); void slotWindowsMenuAboutToShow(); void slotWindowsMenuActivated(int); void slotTileHorizontal(); void slotTileVertical(); void slotPenChanged(RS_Pen p); /** generates a new document for a graphic. */ QC_MDIWindow* slotFileNew(RS_Document* doc=NULL); /** opens a document */ void slotFileOpen(); /** * opens a recent file document * @param id File Menu id of the file */ void slotFileOpenRecent(int id); /** * opens the given file. */ void slotFileOpen(const QString& fileName, RS2::FormatType type); /** saves a document */ void slotFileSave(); /** saves a document under a different filename*/ void slotFileSaveAs(); /** auto-save document */ void slotFileAutoSave(); /** exports the document as bitmap */ void slotFileExport(); bool slotFileExport(const QString& name, const QString& format, QSize size, bool black, bool bw=false); /** closes the current file */ void slotFileClose(); /** closing the current file */ void slotFileClosing(); /** prints the current file */ void slotFilePrint(); /** shows print preview of the current file */ void slotFilePrintPreview(bool on); /** exits the application */ void slotFileQuit(); /** toggle the grid */ void slotViewGrid(bool toggle); /** toggle the draft mode */ void slotViewDraft(bool toggle); /** toggle the statusbar */ void slotViewStatusBar(bool toggle); // void slotBlocksEdit(); void slotOptionsGeneral(); void slotScriptOpenIDE(); void slotScriptRun(); void slotRunStartScript(); void slotRunScript(); void slotRunScript(const QString& name); void slotInsertBlock(); void slotInsertBlock(const QString& name); /** shows an about dlg*/ void slotHelpAbout(); void slotHelpManual(); /** dumps entities to file */ void slotTestDumpEntities(RS_EntityContainer* d=NULL); /** dumps undo info to stdout */ void slotTestDumpUndo(); /** updates all inserts */ void slotTestUpdateInserts(); /** draws some random lines */ void slotTestDrawFreehand(); /** inserts a test block */ void slotTestInsertBlock(); /** inserts a test ellipse */ void slotTestInsertEllipse(); /** inserts a test text */ void slotTestInsertText(); /** inserts a test image */ void slotTestInsertImage(); /** unicode table */ void slotTestUnicode(); /** math experimental */ void slotTestMath01(); /** resizes window to 640x480 for screen shots */ void slotTestResize640(); /** resizes window to 640x480 for screen shots */ void slotTestResize800(); /** resizes window to 640x480 for screen shots */ void slotTestResize1024(); signals: void gridChanged(bool on); void draftChanged(bool on); void printPreviewChanged(bool on); void windowsChanged(bool windowsLeft); public: /** * @return Pointer to application window. */ static QC_ApplicationWindow* getAppWindow() { return appWindow; } /** * @return Pointer to workspace. */ QWorkspace* getWorkspace() { return workspace; } /** * @return Pointer to the currently active MDI Window or NULL if no * MDI Window is active. */ QC_MDIWindow* getMDIWindow() { if (workspace!=NULL) { return (QC_MDIWindow*)workspace->activeWindow(); } else { return NULL; } } /** * Implementation from RS_MainWindowInterface (and QS_ScripterHostInterface). * * @return Pointer to the graphic view of the currently active document * window or NULL if no window is available. */ virtual RS_GraphicView* getGraphicView() { QC_MDIWindow* m = getMDIWindow(); if (m!=NULL) { return m->getGraphicView(); } return NULL; } /** * Implementation from RS_MainWindowInterface (and QS_ScripterHostInterface). * * @return Pointer to the graphic document of the currently active document * window or NULL if no window is available. */ virtual RS_Document* getDocument() { QC_MDIWindow* m = getMDIWindow(); if (m!=NULL) { return m->getDocument(); } return NULL; } /** * Creates a new document. Implementation from RS_MainWindowInterface. */ virtual void createNewDocument( const QString& fileName = QString::null, RS_Document* doc=NULL) { slotFileNew(doc); if (fileName!=QString::null && getDocument()!=NULL) { getDocument()->setFilename(fileName); } } /** * Implementation from QG_MainWindowInterface. * * @return Pointer to this. */ virtual QMainWindow* getMainWindow() { return this; } /** * @return Pointer to action handler. Implementation from QG_MainWindowInterface. */ virtual QG_ActionHandler* getActionHandler() { return actionHandler; } //virtual QToolBar* createToolBar(const QString& name); //virtual void addToolBarButton(QToolBar* tb); /** * @return Pointer to the qsa object. */ #ifdef RS_SCRIPTING QSProject* getQSAProject() { if (scripter!=NULL) { return scripter->getQSAProject(); } else { return NULL; } } #endif void redrawAll(); void updateGrids(); /** * Implementation from QG_MainWindowInterface. */ virtual void setFocus2() { setFocus(); } /** Block list widget */ QG_BlockWidget* getBlockWidget(void) { return blockWidget; } protected: void closeEvent(QCloseEvent*); virtual void mouseReleaseEvent(QMouseEvent* e); private: /** Pointer to the application window (this). */ static QC_ApplicationWindow* appWindow; QTimer *autosaveTimer; /** Workspace for MDI */ QWorkspace* workspace; /** Dialog factory */ QC_DialogFactory* dialogFactory; /** Layer list widget */ QG_LayerWidget* layerWidget; /** Block list widget */ QG_BlockWidget* blockWidget; /** Library browser widget */ QG_LibraryWidget* libraryWidget; /** Layer list dock widget */ QDockWidget* layerDockWindow; /** Block list dock widget */ QDockWidget* blockDockWindow; /** Library list dock widget */ QDockWidget* libraryDockWindow; /** Command line */ QG_CommandWidget* commandWidget; QDockWidget* commandDockWindow; /** Coordinate widget */ QG_CoordinateWidget* coordinateWidget; /** Mouse widget */ QG_MouseWidget* mouseWidget; /** Selection Status */ QG_SelectionWidget* selectionWidget; /** Option widget for individual tool options */ QToolBar* optionWidget; /** Recent files list */ QG_RecentFiles* recentFiles; /** Action handler. */ QG_ActionHandler* actionHandler; #ifdef RS_SCRIPTING /** Scripting interface. */ QS_Scripter* scripter; #endif QMenu* fileMenu; QMenu* windowsMenu; QMenu* scriptMenu; QMenu* helpMenu; QMenu* testMenu; /** the main toolbars */ QToolBar* fileToolBar; QToolBar* editToolBar; QToolBar* zoomToolBar; // Toolbar for selecting the current pen QG_PenToolBar* penToolBar; // Toolbar for CAD tools QG_CadToolBar* cadToolBar; QHelpEngine* helpEngine; QDockWidget *helpWindow; QAction* scriptOpenIDE; QAction* scriptRun; QAction* helpAboutApp; QAction* helpManual; QAction *testDumpEntities; QAction *testDumpUndo; QAction *testUpdateInserts; QAction *testDrawFreehand; QAction *testInsertBlock; QAction *testInsertText; QAction *testInsertImage; QAction *testUnicode; QAction *testInsertEllipse; QAction *testMath01; QAction *testResize640; QAction *testResize800; QAction *testResize1024; //Plugin support private: void loadPlugins(); QMenu *findMenu(const QString &searchMenu, const QObjectList thisMenuList, const QString& currentEntry); QList<QC_PluginInterface*> loadedPlugins; public slots: void execPlug(); }; #endif 给出完整的代码注释
07-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值