mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-31 20:58:07 -06:00
Move utilities to core/utils folder.
Also move the names to Utils namespace.
This commit is contained in:
@@ -48,10 +48,10 @@ MagnetUri::MagnetUri(const QString &url)
|
||||
|
||||
m_valid = true;
|
||||
m_hash = m_addTorrentParams.info_hash;
|
||||
m_name = String::fromStdString(m_addTorrentParams.name);
|
||||
m_name = Utils::String::fromStdString(m_addTorrentParams.name);
|
||||
|
||||
foreach (const std::string &tracker, m_addTorrentParams.trackers)
|
||||
m_trackers.append(String::fromStdString(tracker));
|
||||
m_trackers.append(Utils::String::fromStdString(tracker));
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM >= 10000
|
||||
foreach (const std::string &urlSeed, m_addTorrentParams.url_seeds)
|
||||
|
||||
@@ -202,7 +202,7 @@ PeerAddress PeerInfo::address() const
|
||||
|
||||
QString PeerInfo::client() const
|
||||
{
|
||||
return String::fromStdString(m_nativeInfo.client);
|
||||
return Utils::String::fromStdString(m_nativeInfo.client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ using namespace BitTorrent;
|
||||
#include "geoipmanager.h"
|
||||
#endif
|
||||
|
||||
#include "core/misc.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/utils/misc.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "core/logger.h"
|
||||
#include "core/preferences.h"
|
||||
@@ -163,7 +163,7 @@ Session::Session(QObject *parent)
|
||||
// Construct session
|
||||
libt::fingerprint fingerprint(PEER_ID, VERSION_MAJOR, VERSION_MINOR, VERSION_BUGFIX, VERSION_BUILD);
|
||||
m_nativeSession = new libt::session(fingerprint, 0);
|
||||
Logger::instance()->addMessage("Peer ID: " + String::fromStdString(fingerprint.to_string()));
|
||||
Logger::instance()->addMessage("Peer ID: " + Utils::String::fromStdString(fingerprint.to_string()));
|
||||
|
||||
m_nativeSession->set_alert_dispatch(boost::bind(&Session::dispatchAlerts, this, _1));
|
||||
|
||||
@@ -318,12 +318,12 @@ Session *Session::instance()
|
||||
|
||||
void Session::loadState()
|
||||
{
|
||||
const QString statePath = fsutils::cacheLocation() + QLatin1String("/ses_state");
|
||||
const QString statePath = Utils::Fs::cacheLocation() + QLatin1String("/ses_state");
|
||||
if (!QFile::exists(statePath)) return;
|
||||
|
||||
if (QFile(statePath).size() == 0) {
|
||||
// Remove empty invalid state file
|
||||
fsutils::forceRemove(statePath);
|
||||
Utils::Fs::forceRemove(statePath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ void Session::saveState()
|
||||
{
|
||||
qDebug("Saving session state to disk...");
|
||||
|
||||
const QString state_path = fsutils::cacheLocation() + QLatin1String("/ses_state");
|
||||
const QString state_path = Utils::Fs::cacheLocation() + QLatin1String("/ses_state");
|
||||
libt::entry session_state;
|
||||
m_nativeSession->save_state(session_state);
|
||||
std::vector<char> out;
|
||||
@@ -364,7 +364,7 @@ void Session::setSessionSettings()
|
||||
libt::session_settings sessionSettings = m_nativeSession->settings();
|
||||
sessionSettings.user_agent = "qBittorrent " VERSION;
|
||||
//std::cout << "HTTP user agent is " << sessionSettings.user_agent << std::endl;
|
||||
logger->addMessage(tr("HTTP user agent is %1").arg(String::fromStdString(sessionSettings.user_agent)));
|
||||
logger->addMessage(tr("HTTP user agent is %1").arg(Utils::String::fromStdString(sessionSettings.user_agent)));
|
||||
|
||||
sessionSettings.upnp_ignore_nonrouters = true;
|
||||
sessionSettings.use_dht_as_fallback = false;
|
||||
@@ -422,7 +422,7 @@ void Session::setSessionSettings()
|
||||
// IP address to announce to trackers
|
||||
QString announce_ip = pref->getNetworkAddress();
|
||||
if (!announce_ip.isEmpty())
|
||||
sessionSettings.announce_ip = String::toStdString(announce_ip);
|
||||
sessionSettings.announce_ip = Utils::String::toStdString(announce_ip);
|
||||
// Super seeding
|
||||
sessionSettings.strict_super_seeding = pref->isSuperSeedingEnabled();
|
||||
// * Max Half-open connections
|
||||
@@ -668,13 +668,13 @@ void Session::configure()
|
||||
libt::proxy_settings proxySettings;
|
||||
if (pref->isProxyEnabled()) {
|
||||
qDebug("Enabling P2P proxy");
|
||||
proxySettings.hostname = String::toStdString(pref->getProxyIp());
|
||||
proxySettings.hostname = Utils::String::toStdString(pref->getProxyIp());
|
||||
qDebug("hostname is %s", proxySettings.hostname.c_str());
|
||||
proxySettings.port = pref->getProxyPort();
|
||||
qDebug("port is %d", proxySettings.port);
|
||||
if (pref->isProxyAuthEnabled()) {
|
||||
proxySettings.username = String::toStdString(pref->getProxyUsername());
|
||||
proxySettings.password = String::toStdString(pref->getProxyPassword());
|
||||
proxySettings.username = Utils::String::toStdString(pref->getProxyUsername());
|
||||
proxySettings.password = Utils::String::toStdString(pref->getProxyPassword());
|
||||
qDebug("username is %s", proxySettings.username.c_str());
|
||||
qDebug("password is %s", proxySettings.password.c_str());
|
||||
}
|
||||
@@ -780,7 +780,7 @@ void Session::handleDownloadFinished(const QString &url, const QString &filePath
|
||||
{
|
||||
emit downloadFromUrlFinished(url);
|
||||
addTorrent_impl(m_downloadedTorrents.take(url), MagnetUri(), TorrentInfo::loadFromFile(filePath));
|
||||
fsutils::forceRemove(filePath); // remove temporary file
|
||||
Utils::Fs::forceRemove(filePath); // remove temporary file
|
||||
}
|
||||
|
||||
void Session::changeSpeedLimitMode(bool alternative)
|
||||
@@ -870,8 +870,8 @@ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles)
|
||||
// Remove unwanted and incomplete files
|
||||
foreach (const QString &unwantedFile, unwantedFiles) {
|
||||
qDebug("Removing unwanted file: %s", qPrintable(unwantedFile));
|
||||
fsutils::forceRemove(unwantedFile);
|
||||
const QString parentFolder = fsutils::branchPath(unwantedFile);
|
||||
Utils::Fs::forceRemove(unwantedFile);
|
||||
const QString parentFolder = Utils::Fs::branchPath(unwantedFile);
|
||||
qDebug("Attempt to remove parent folder (if empty): %s", qPrintable(parentFolder));
|
||||
QDir().rmpath(parentFolder);
|
||||
}
|
||||
@@ -883,7 +883,7 @@ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles)
|
||||
filters << QString("%1.*").arg(torrent->hash());
|
||||
const QStringList files = resumeDataDir.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||
foreach (const QString &file, files)
|
||||
fsutils::forceRemove(resumeDataDir.absoluteFilePath(file));
|
||||
Utils::Fs::forceRemove(resumeDataDir.absoluteFilePath(file));
|
||||
|
||||
if (deleteLocalFiles)
|
||||
Logger::instance()->addMessage(tr("'%1' was removed from transfer list and hard disk.", "'xxx.avi' was removed...").arg(torrent->name()));
|
||||
@@ -1038,10 +1038,10 @@ bool Session::addTorrent(QString source, const AddTorrentParams ¶ms)
|
||||
|
||||
if (source.startsWith("bc://bt/", Qt::CaseInsensitive)) {
|
||||
qDebug("Converting bc link to magnet link");
|
||||
source = misc::bcLinkToMagnet(source);
|
||||
source = Utils::Misc::bcLinkToMagnet(source);
|
||||
}
|
||||
|
||||
if (misc::isUrl(source)) {
|
||||
if (Utils::Misc::isUrl(source)) {
|
||||
Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source));
|
||||
// Launch downloader
|
||||
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */);
|
||||
@@ -1164,7 +1164,7 @@ bool Session::addTorrent_impl(const AddTorrentData &addData, const MagnetUri &ma
|
||||
savePath += "/";
|
||||
}
|
||||
|
||||
p.save_path = String::toStdString(fsutils::toNativePath(savePath));
|
||||
p.save_path = Utils::String::toStdString(Utils::Fs::toNativePath(savePath));
|
||||
// Check if save path exists, creating it otherwise
|
||||
if (!QDir(savePath).exists())
|
||||
QDir().mkpath(savePath);
|
||||
@@ -1214,7 +1214,7 @@ bool Session::loadMetadata(const QString &magnetUri)
|
||||
#endif
|
||||
|
||||
QString savePath = QString("%1/%2").arg(QDir::tempPath()).arg(hash);
|
||||
p.save_path = String::toStdString(fsutils::toNativePath(savePath));
|
||||
p.save_path = Utils::String::toStdString(Utils::Fs::toNativePath(savePath));
|
||||
// Check if save path exists, creating it otherwise
|
||||
if (!QDir(savePath).exists())
|
||||
QDir().mkpath(savePath);
|
||||
@@ -1253,7 +1253,7 @@ void Session::exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolde
|
||||
QDir exportPath(folder == TorrentExportFolder::Regular ? Preferences::instance()->getTorrentExportDir() : Preferences::instance()->getFinishedTorrentExportDir());
|
||||
if (exportPath.exists() || exportPath.mkpath(exportPath.absolutePath())) {
|
||||
QString newTorrentPath = exportPath.absoluteFilePath(torrentFilename);
|
||||
if (QFile::exists(newTorrentPath) && fsutils::sameFiles(torrentPath, newTorrentPath)) {
|
||||
if (QFile::exists(newTorrentPath) && Utils::Fs::sameFiles(torrentPath, newTorrentPath)) {
|
||||
// Append hash to torrent name to make it unique
|
||||
newTorrentPath = exportPath.absoluteFilePath(torrent->name() + "-" + torrentFilename);
|
||||
}
|
||||
@@ -1285,7 +1285,7 @@ void Session::exportTorrentFiles(QString path)
|
||||
if (QFile::exists(srcPath)) {
|
||||
QString dstPath = exportDir.absoluteFilePath(QString("%1.torrent").arg(torrent->name()));
|
||||
if (QFile::exists(dstPath)) {
|
||||
if (!fsutils::sameFiles(srcPath, dstPath)) {
|
||||
if (!Utils::Fs::sameFiles(srcPath, dstPath)) {
|
||||
dstPath = exportDir.absoluteFilePath(QString("%1-%2.torrent").arg(torrent->name()).arg(torrent->hash()));
|
||||
}
|
||||
else {
|
||||
@@ -1375,7 +1375,7 @@ void Session::enableDHT(bool enable)
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
qDebug("Could not enable DHT, reason: %s", e.what());
|
||||
logger->addMessage(tr("DHT support [OFF]. Reason: %1").arg(String::fromStdString(e.what())), Log::CRITICAL);
|
||||
logger->addMessage(tr("DHT support [OFF]. Reason: %1").arg(Utils::String::fromStdString(e.what())), Log::CRITICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1442,7 +1442,7 @@ void Session::setDefaultSavePath(const QString &path)
|
||||
{
|
||||
if (path.isEmpty()) return;
|
||||
|
||||
QString defaultSavePath = fsutils::fromNativePath(path);
|
||||
QString defaultSavePath = Utils::Fs::fromNativePath(path);
|
||||
if (!defaultSavePath.endsWith("/"))
|
||||
defaultSavePath += "/";
|
||||
if (m_defaultSavePath != defaultSavePath) {
|
||||
@@ -1457,7 +1457,7 @@ void Session::setDefaultTempPath(const QString &path)
|
||||
QString tempPath;
|
||||
|
||||
if (!path.isEmpty()) {
|
||||
tempPath = fsutils::fromNativePath(path);
|
||||
tempPath = Utils::Fs::fromNativePath(path);
|
||||
if (!tempPath.endsWith("/"))
|
||||
tempPath += "/";
|
||||
}
|
||||
@@ -1506,7 +1506,7 @@ void Session::setListeningPort(int port)
|
||||
m_nativeSession->listen_on(ports, ec, 0, libt::session::listen_no_system_port);
|
||||
|
||||
if (ec)
|
||||
logger->addMessage(tr("qBittorrent failed to listen on any interface port: %1. Reason: %2", "e.g: qBittorrent failed to listen on any interface port: TCP/6881. Reason: no such interface" ).arg(QString::number(port)).arg(String::fromStdString(ec.message())), Log::CRITICAL);
|
||||
logger->addMessage(tr("qBittorrent failed to listen on any interface port: %1. Reason: %2", "e.g: qBittorrent failed to listen on any interface port: TCP/6881. Reason: no such interface" ).arg(QString::number(port)).arg(Utils::String::fromStdString(ec.message())), Log::CRITICAL);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1716,7 +1716,7 @@ void Session::handleTorrentFinished(TorrentHandle *const torrent)
|
||||
}
|
||||
else {
|
||||
qDebug("Caught error loading torrent");
|
||||
Logger::instance()->addMessage(tr("Unable to decode %1 torrent file.").arg(fsutils::toNativePath(torrentFullpath)), Log::CRITICAL);
|
||||
Logger::instance()->addMessage(tr("Unable to decode %1 torrent file.").arg(Utils::Fs::toNativePath(torrentFullpath)), Log::CRITICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1773,7 +1773,7 @@ bool Session::hasPerTorrentRatioLimit() const
|
||||
|
||||
void Session::initResumeFolder()
|
||||
{
|
||||
m_resumeFolderPath = fsutils::expandPathAbs(fsutils::QDesktopServicesDataLocation() + RESUME_FOLDER);
|
||||
m_resumeFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + RESUME_FOLDER);
|
||||
QDir resumeFolderDir(m_resumeFolderPath);
|
||||
if (resumeFolderDir.exists() || resumeFolderDir.mkpath(resumeFolderDir.absolutePath())) {
|
||||
m_resumeFolderLock.setFileName(resumeFolderDir.absoluteFilePath("session.lock"));
|
||||
@@ -1795,9 +1795,9 @@ void Session::enableIPFilter(const QString &filterPath, bool force)
|
||||
connect(m_filterParser.data(), SIGNAL(IPFilterParsed(int)), SLOT(handleIPFilterParsed(int)));
|
||||
connect(m_filterParser.data(), SIGNAL(IPFilterError()), SLOT(handleIPFilterError()));
|
||||
}
|
||||
if (m_filterPath.isEmpty() || m_filterPath != fsutils::fromNativePath(filterPath) || force) {
|
||||
m_filterPath = fsutils::fromNativePath(filterPath);
|
||||
m_filterParser->processFilterFile(fsutils::fromNativePath(filterPath));
|
||||
if (m_filterPath.isEmpty() || m_filterPath != Utils::Fs::fromNativePath(filterPath) || force) {
|
||||
m_filterPath = Utils::Fs::fromNativePath(filterPath);
|
||||
m_filterParser->processFilterFile(Utils::Fs::fromNativePath(filterPath));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1824,7 +1824,7 @@ void Session::recursiveTorrentDownload(const InfoHash &hash)
|
||||
Logger::instance()->addMessage(
|
||||
tr("Recursive download of file %1 embedded in torrent %2"
|
||||
, "Recursive download of test.torrent embedded in torrent test2")
|
||||
.arg(fsutils::toNativePath(torrentRelpath)).arg(torrent->name()));
|
||||
.arg(Utils::Fs::toNativePath(torrentRelpath)).arg(torrent->name()));
|
||||
const QString torrentFullpath = torrent->savePath() + "/" + torrentRelpath;
|
||||
|
||||
AddTorrentParams params;
|
||||
@@ -1857,18 +1857,18 @@ void Session::setProxySettings(libt::proxy_settings proxySettings)
|
||||
QString proxy_str;
|
||||
switch(proxySettings.type) {
|
||||
case libt::proxy_settings::http_pw:
|
||||
proxy_str = QString("http://%1:%2@%3:%4").arg(String::fromStdString(proxySettings.username)).arg(String::fromStdString(proxySettings.password))
|
||||
.arg(String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
proxy_str = QString("http://%1:%2@%3:%4").arg(Utils::String::fromStdString(proxySettings.username)).arg(Utils::String::fromStdString(proxySettings.password))
|
||||
.arg(Utils::String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
break;
|
||||
case libt::proxy_settings::http:
|
||||
proxy_str = QString("http://%1:%2").arg(String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
proxy_str = QString("http://%1:%2").arg(Utils::String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
break;
|
||||
case libt::proxy_settings::socks5:
|
||||
proxy_str = QString("%1:%2").arg(String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
proxy_str = QString("%1:%2").arg(Utils::String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
break;
|
||||
case libt::proxy_settings::socks5_pw:
|
||||
proxy_str = QString("%1:%2@%3:%4").arg(String::fromStdString(proxySettings.username)).arg(String::fromStdString(proxySettings.password))
|
||||
.arg(String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
proxy_str = QString("%1:%2@%3:%4").arg(Utils::String::fromStdString(proxySettings.username)).arg(Utils::String::fromStdString(proxySettings.password))
|
||||
.arg(Utils::String::fromStdString(proxySettings.hostname)).arg(proxySettings.port);
|
||||
break;
|
||||
default:
|
||||
qDebug("Disabling HTTP communications proxy");
|
||||
@@ -1930,11 +1930,11 @@ void Session::startUpTorrents()
|
||||
qDebug("Starting up torrent %s ...", qPrintable(hash));
|
||||
if (!addTorrent_impl(resumeData, MagnetUri(), TorrentInfo::loadFromFile(filePath), data))
|
||||
logger->addMessage(tr("Unable to resume torrent '%1'.", "e.g: Unable to resume torrent 'hash'.")
|
||||
.arg(fsutils::toNativePath(hash)), Log::CRITICAL);
|
||||
.arg(Utils::Fs::toNativePath(hash)), Log::CRITICAL);
|
||||
}
|
||||
else {
|
||||
logger->addMessage(tr("Unable to resume torrent '%1': torrent file not found.", "e.g: Unable to resume torrent 'hash': torrent file not found.")
|
||||
.arg(fsutils::toNativePath(hash)), Log::CRITICAL);
|
||||
.arg(Utils::Fs::toNativePath(hash)), Log::CRITICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2074,7 +2074,7 @@ void Session::handleAlert(libt::alert *a)
|
||||
}
|
||||
}
|
||||
catch (std::exception &exc) {
|
||||
qWarning() << "Caught exception in readAlerts(): " << String::fromStdString(exc.what());
|
||||
qWarning() << "Caught exception in readAlerts(): " << Utils::String::fromStdString(exc.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2090,7 +2090,7 @@ void Session::handleAddTorrentAlert(libtorrent::add_torrent_alert *p)
|
||||
Logger *const logger = Logger::instance();
|
||||
if (p->error) {
|
||||
qDebug("/!\\ Error: Failed to add torrent!");
|
||||
QString msg = String::fromStdString(p->message());
|
||||
QString msg = Utils::String::fromStdString(p->message());
|
||||
logger->addMessage(tr("Couldn't add torrent. Reason: %1").arg(msg), Log::WARNING);
|
||||
emit addTorrentFailed(msg);
|
||||
return;
|
||||
@@ -2166,7 +2166,7 @@ void Session::handleTorrentDeletedAlert(libt::torrent_deleted_alert *p)
|
||||
qDebug("A torrent was deleted from the hard disk, attempting to remove the root folder too...");
|
||||
const QString dirpath = m_savePathsToRemove.take(p->info_hash);
|
||||
qDebug() << "Removing save path: " << dirpath << "...";
|
||||
bool ok = fsutils::smartRemoveEmptyFolderTree(dirpath);
|
||||
bool ok = Utils::Fs::smartRemoveEmptyFolderTree(dirpath);
|
||||
Q_UNUSED(ok);
|
||||
qDebug() << "Folder was removed: " << ok;
|
||||
}
|
||||
@@ -2194,7 +2194,7 @@ void Session::handleFileErrorAlert(libt::file_error_alert *p)
|
||||
// NOTE: Check this function!
|
||||
TorrentHandle *const torrent = m_torrents.value(p->handle.info_hash());
|
||||
if (torrent) {
|
||||
QString msg = String::fromStdString(p->message());
|
||||
QString msg = Utils::String::fromStdString(p->message());
|
||||
Logger::instance()->addMessage(tr("An I/O error occurred, '%1' paused. %2")
|
||||
.arg(torrent->name()).arg(msg));
|
||||
emit fullDiskError(torrent, msg);
|
||||
@@ -2203,13 +2203,13 @@ void Session::handleFileErrorAlert(libt::file_error_alert *p)
|
||||
|
||||
void Session::handlePortmapWarningAlert(libt::portmap_error_alert *p)
|
||||
{
|
||||
Logger::instance()->addMessage(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(String::fromStdString(p->message())), Log::CRITICAL);
|
||||
Logger::instance()->addMessage(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(Utils::String::fromStdString(p->message())), Log::CRITICAL);
|
||||
}
|
||||
|
||||
void Session::handlePortmapAlert(libt::portmap_alert *p)
|
||||
{
|
||||
qDebug("UPnP Success, msg: %s", p->message().c_str());
|
||||
Logger::instance()->addMessage(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(String::fromStdString(p->message())), Log::INFO);
|
||||
Logger::instance()->addMessage(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(Utils::String::fromStdString(p->message())), Log::INFO);
|
||||
}
|
||||
|
||||
void Session::handlePeerBlockedAlert(libt::peer_blocked_alert *p)
|
||||
@@ -2257,7 +2257,7 @@ void Session::handlePeerBanAlert(libt::peer_ban_alert *p)
|
||||
|
||||
void Session::handleUrlSeedAlert(libt::url_seed_alert *p)
|
||||
{
|
||||
Logger::instance()->addMessage(tr("Url seed lookup failed for url: %1, message: %2").arg(String::fromStdString(p->url)).arg(String::fromStdString(p->message())), Log::CRITICAL);
|
||||
Logger::instance()->addMessage(tr("Url seed lookup failed for url: %1, message: %2").arg(Utils::String::fromStdString(p->url)).arg(Utils::String::fromStdString(p->message())), Log::CRITICAL);
|
||||
}
|
||||
|
||||
void Session::handleListenSucceededAlert(libt::listen_succeeded_alert *p)
|
||||
@@ -2304,7 +2304,7 @@ void Session::handleListenFailedAlert(libt::listen_failed_alert *p)
|
||||
tr("qBittorrent failed listening on interface %1 port: %2/%3. Reason: %4",
|
||||
"e.g: qBittorrent failed listening on interface 192.168.0.1 port: TCP/6881. Reason: already in use")
|
||||
.arg(p->endpoint.address().to_string(ec).c_str()).arg(proto).arg(QString::number(p->endpoint.port()))
|
||||
.arg(String::fromStdString(p->error.message())), Log::CRITICAL);
|
||||
.arg(Utils::String::fromStdString(p->error.message())), Log::CRITICAL);
|
||||
}
|
||||
|
||||
void Session::handleExternalIPAlert(libt::external_ip_alert *p)
|
||||
@@ -2367,10 +2367,10 @@ bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out)
|
||||
if ((fast.type() != libt::lazy_entry::dict_t) && !ec) return false;
|
||||
|
||||
out.addedTime = QDateTime::fromTime_t(fast.dict_find_int_value("qBt-addedTime"));
|
||||
out.savePath = fsutils::fromNativePath(QString::fromUtf8(fast.dict_find_string_value("qBt-savePath").c_str()));
|
||||
out.ratioLimit = QString::fromUtf8(fast.dict_find_string_value("qBt-ratioLimit").c_str()).toDouble();
|
||||
out.label = QString::fromUtf8(fast.dict_find_string_value("qBt-label").c_str());
|
||||
out.name = QString::fromUtf8(fast.dict_find_string_value("qBt-name").c_str());
|
||||
out.savePath = Utils::Fs::fromNativePath(Utils::String::fromStdString(fast.dict_find_string_value("qBt-savePath")));
|
||||
out.ratioLimit = Utils::String::fromStdString(fast.dict_find_string_value("qBt-ratioLimit")).toDouble();
|
||||
out.label = Utils::String::fromStdString(fast.dict_find_string_value("qBt-label"));
|
||||
out.name = Utils::String::fromStdString(fast.dict_find_string_value("qBt-name"));
|
||||
out.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus");
|
||||
out.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
|
||||
|
||||
@@ -2384,7 +2384,7 @@ bool Session::writeResumeDataFile(TorrentHandle *const torrent, const libt::entr
|
||||
QStringList filters(QString("%1.fastresume.*").arg(torrent->hash()));
|
||||
const QStringList files = resumeDataDir.entryList(filters, QDir::Files, QDir::Unsorted);
|
||||
foreach (const QString &file, files)
|
||||
fsutils::forceRemove(resumeDataDir.absoluteFilePath(file));
|
||||
Utils::Fs::forceRemove(resumeDataDir.absoluteFilePath(file));
|
||||
|
||||
QString filename = QString("%1.fastresume.%2").arg(torrent->hash()).arg(torrent->queuePosition());
|
||||
QString filepath = resumeDataDir.absoluteFilePath(filename);
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/misc.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "torrentcreatorthread.h"
|
||||
|
||||
@@ -73,10 +73,10 @@ TorrentCreatorThread::~TorrentCreatorThread()
|
||||
void TorrentCreatorThread::create(const QString &inputPath, const QString &savePath, const QStringList &trackers,
|
||||
const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize)
|
||||
{
|
||||
m_inputPath = fsutils::fromNativePath(inputPath);
|
||||
m_savePath = fsutils::fromNativePath(savePath);
|
||||
m_inputPath = Utils::Fs::fromNativePath(inputPath);
|
||||
m_savePath = Utils::Fs::fromNativePath(savePath);
|
||||
if (QFile(m_savePath).exists())
|
||||
fsutils::forceRemove(m_savePath);
|
||||
Utils::Fs::forceRemove(m_savePath);
|
||||
m_trackers = trackers;
|
||||
m_urlSeeds = urlSeeds;
|
||||
m_comment = comment;
|
||||
@@ -105,14 +105,14 @@ void TorrentCreatorThread::run()
|
||||
try {
|
||||
libt::file_storage fs;
|
||||
// Adding files to the torrent
|
||||
libt::add_files(fs, String::toStdString(fsutils::toNativePath(m_inputPath)), fileFilter);
|
||||
libt::add_files(fs, Utils::String::toStdString(Utils::Fs::toNativePath(m_inputPath)), fileFilter);
|
||||
if (m_abort) return;
|
||||
|
||||
libt::create_torrent t(fs, m_pieceSize);
|
||||
|
||||
// Add url seeds
|
||||
foreach (const QString &seed, m_urlSeeds)
|
||||
t.add_url_seed(String::toStdString(seed.trimmed()));
|
||||
t.add_url_seed(Utils::String::toStdString(seed.trimmed()));
|
||||
|
||||
int tier = 0;
|
||||
bool newline = false;
|
||||
@@ -124,14 +124,14 @@ void TorrentCreatorThread::run()
|
||||
newline = true;
|
||||
continue;
|
||||
}
|
||||
t.add_tracker(String::toStdString(tracker.trimmed()), tier);
|
||||
t.add_tracker(Utils::String::toStdString(tracker.trimmed()), tier);
|
||||
newline = false;
|
||||
}
|
||||
if (m_abort) return;
|
||||
|
||||
// calculate the hash for all pieces
|
||||
const QString parentPath = fsutils::branchPath(m_inputPath) + "/";
|
||||
libt::set_piece_hashes(t, String::toStdString(fsutils::toNativePath(parentPath)), boost::bind(&TorrentCreatorThread::sendProgressSignal, this, _1, t.num_pieces()));
|
||||
const QString parentPath = Utils::Fs::branchPath(m_inputPath) + "/";
|
||||
libt::set_piece_hashes(t, Utils::String::toStdString(Utils::Fs::toNativePath(parentPath)), boost::bind(&TorrentCreatorThread::sendProgressSignal, this, _1, t.num_pieces()));
|
||||
// Set qBittorrent as creator and add user comment to
|
||||
// torrent_info structure
|
||||
t.set_creator(creator_str.toUtf8().constData());
|
||||
@@ -144,12 +144,12 @@ void TorrentCreatorThread::run()
|
||||
qDebug("Saving to %s", qPrintable(m_savePath));
|
||||
#ifdef _MSC_VER
|
||||
wchar_t *savePathW = new wchar_t[m_savePath.length() + 1];
|
||||
int len = fsutils::toNativePath(m_savePath).toWCharArray(savePathW);
|
||||
int len = Utils::Fs::toNativePath(m_savePath).toWCharArray(savePathW);
|
||||
savePathW[len] = L'\0';
|
||||
std::ofstream outfile(savePathW, std::ios_base::out | std::ios_base::binary);
|
||||
delete[] savePathW;
|
||||
#else
|
||||
std::ofstream outfile(fsutils::toNativePath(m_savePath).toLocal8Bit().constData(), std::ios_base::out | std::ios_base::binary);
|
||||
std::ofstream outfile(Utils::Fs::toNativePath(m_savePath).toLocal8Bit().constData(), std::ios_base::out | std::ios_base::binary);
|
||||
#endif
|
||||
if (outfile.fail())
|
||||
throw std::exception();
|
||||
@@ -161,6 +161,6 @@ void TorrentCreatorThread::run()
|
||||
emit creationSuccess(m_savePath, parentPath);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
emit creationFailure(String::fromStdString(e.what()));
|
||||
emit creationFailure(Utils::String::fromStdString(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,11 @@
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/logger.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/misc.h"
|
||||
#include "session.h"
|
||||
#include "peerinfo.h"
|
||||
#include "trackerentry.h"
|
||||
@@ -186,7 +186,7 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle
|
||||
, m_state(TorrentState::Unknown)
|
||||
, m_name(data.name)
|
||||
, m_addedTime(data.resumed ? data.addedTime : QDateTime::currentDateTime())
|
||||
, m_savePath(fsutils::toNativePath(data.savePath))
|
||||
, m_savePath(Utils::Fs::toNativePath(data.savePath))
|
||||
, m_label(data.label)
|
||||
, m_hasSeedStatus(data.resumed ? data.hasSeedStatus : false)
|
||||
, m_ratioLimit(data.resumed ? data.ratioLimit : (data.ignoreShareRatio ? NO_RATIO_LIMIT : USE_GLOBAL_RATIO))
|
||||
@@ -230,7 +230,7 @@ QString TorrentHandle::name() const
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
name = m_nativeName;
|
||||
#else
|
||||
name = String::fromStdString(m_nativeStatus.name);
|
||||
name = Utils::String::fromStdString(m_nativeStatus.name);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -293,12 +293,12 @@ qlonglong TorrentHandle::wastedSize() const
|
||||
|
||||
QString TorrentHandle::currentTracker() const
|
||||
{
|
||||
return String::fromStdString(m_nativeStatus.current_tracker);
|
||||
return Utils::String::fromStdString(m_nativeStatus.current_tracker);
|
||||
}
|
||||
|
||||
QString TorrentHandle::savePath() const
|
||||
{
|
||||
return fsutils::fromNativePath(m_savePath);
|
||||
return Utils::Fs::fromNativePath(m_savePath);
|
||||
}
|
||||
|
||||
QString TorrentHandle::rootPath() const
|
||||
@@ -318,13 +318,13 @@ QString TorrentHandle::nativeActualSavePath() const
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return m_nativeSavePath;
|
||||
#else
|
||||
return String::fromStdString(m_nativeStatus.save_path);
|
||||
return Utils::String::fromStdString(m_nativeStatus.save_path);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString TorrentHandle::actualSavePath() const
|
||||
{
|
||||
return fsutils::fromNativePath(nativeActualSavePath());
|
||||
return Utils::Fs::fromNativePath(nativeActualSavePath());
|
||||
}
|
||||
|
||||
QList<TrackerEntry> TorrentHandle::trackers() const
|
||||
@@ -437,7 +437,7 @@ bool TorrentHandle::addUrlSeed(const QUrl &urlSeed)
|
||||
QList<QUrl> seeds = urlSeeds();
|
||||
if (seeds.contains(urlSeed)) return false;
|
||||
|
||||
SAFE_CALL_BOOL(add_url_seed, String::toStdString(urlSeed.toString()));
|
||||
SAFE_CALL_BOOL(add_url_seed, Utils::String::toStdString(urlSeed.toString()));
|
||||
}
|
||||
|
||||
bool TorrentHandle::removeUrlSeed(const QUrl &urlSeed)
|
||||
@@ -445,13 +445,13 @@ bool TorrentHandle::removeUrlSeed(const QUrl &urlSeed)
|
||||
QList<QUrl> seeds = urlSeeds();
|
||||
if (!seeds.contains(urlSeed)) return false;
|
||||
|
||||
SAFE_CALL_BOOL(remove_url_seed, String::toStdString(urlSeed.toString()));
|
||||
SAFE_CALL_BOOL(remove_url_seed, Utils::String::toStdString(urlSeed.toString()));
|
||||
}
|
||||
|
||||
bool TorrentHandle::connectPeer(const PeerAddress &peerAddress)
|
||||
{
|
||||
libt::error_code ec;
|
||||
libt::address addr = libt::address::from_string(String::toStdString(peerAddress.ip.toString()), ec);
|
||||
libt::address addr = libt::address::from_string(Utils::String::toStdString(peerAddress.ip.toString()), ec);
|
||||
if (ec) return false;
|
||||
|
||||
libt::asio::ip::tcp::endpoint ep(addr, peerAddress.port);
|
||||
@@ -479,7 +479,7 @@ QString TorrentHandle::savePathParsed() const
|
||||
else
|
||||
p = savePath();
|
||||
|
||||
return fsutils::toNativePath(p);
|
||||
return Utils::Fs::toNativePath(p);
|
||||
}
|
||||
|
||||
int TorrentHandle::filesCount() const
|
||||
@@ -544,7 +544,7 @@ QString TorrentHandle::filePath(int index) const
|
||||
QString TorrentHandle::fileName(int index) const
|
||||
{
|
||||
if (!hasMetadata()) return QString();
|
||||
return fsutils::fileName(filePath(index));
|
||||
return Utils::Fs::fileName(filePath(index));
|
||||
}
|
||||
|
||||
qlonglong TorrentHandle::fileSize(int index) const
|
||||
@@ -561,7 +561,7 @@ QStringList TorrentHandle::absoluteFilePaths() const
|
||||
QDir saveDir(actualSavePath());
|
||||
QStringList res;
|
||||
for (int i = 0; i < filesCount(); ++i)
|
||||
res << fsutils::expandPathAbs(saveDir.absoluteFilePath(filePath(i)));
|
||||
res << Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i)));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -577,7 +577,7 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const
|
||||
int count = static_cast<int>(fp.size());
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (fp[i] == 0) {
|
||||
const QString path = fsutils::expandPathAbs(saveDir.absoluteFilePath(filePath(i)));
|
||||
const QString path = Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i)));
|
||||
if (path.contains(".unwanted"))
|
||||
res << path;
|
||||
}
|
||||
@@ -720,8 +720,8 @@ bool TorrentHandle::hasFirstLastPiecePriority() const
|
||||
bool found = false;
|
||||
int count = static_cast<int>(fp.size());
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const QString ext = fsutils::fileExtension(filePath(i));
|
||||
if (misc::isPreviewable(ext) && (fp[i] > 0)) {
|
||||
const QString ext = Utils::Fs::fileExtension(filePath(i));
|
||||
if (Utils::Misc::isPreviewable(ext) && (fp[i] > 0)) {
|
||||
extremities = fileExtremityPieces(i);
|
||||
found = true;
|
||||
break;
|
||||
@@ -824,7 +824,7 @@ int TorrentHandle::queuePosition() const
|
||||
|
||||
QString TorrentHandle::error() const
|
||||
{
|
||||
return String::fromStdString(m_nativeStatus.error);
|
||||
return Utils::String::fromStdString(m_nativeStatus.error);
|
||||
}
|
||||
|
||||
qlonglong TorrentHandle::totalDownload() const
|
||||
@@ -1114,7 +1114,7 @@ void TorrentHandle::move(QString path)
|
||||
// even if new path same as default.
|
||||
m_useDefaultSavePath = false;
|
||||
|
||||
path = fsutils::toNativePath(path);
|
||||
path = Utils::Fs::toNativePath(path);
|
||||
if (path == savePath()) return;
|
||||
|
||||
if (!useTempPath()) {
|
||||
@@ -1183,8 +1183,8 @@ void TorrentHandle::setFirstLastPiecePriority(bool b)
|
||||
int nbfiles = static_cast<int>(fp.size());
|
||||
for (int index = 0; index < nbfiles; ++index) {
|
||||
const QString path = filePath(index);
|
||||
const QString ext = fsutils::fileExtension(path);
|
||||
if (misc::isPreviewable(ext) && (fp[index] > 0)) {
|
||||
const QString ext = Utils::Fs::fileExtension(path);
|
||||
if (Utils::Misc::isPreviewable(ext) && (fp[index] > 0)) {
|
||||
qDebug() << "File" << path << "is previewable, toggle downloading of first/last pieces first";
|
||||
// Determine the priority to set
|
||||
int prio = b ? 7 : fp[index];
|
||||
@@ -1258,7 +1258,7 @@ void TorrentHandle::setTrackerLogin(const QString &username, const QString &pass
|
||||
void TorrentHandle::renameFile(int index, const QString &name)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << index << name;
|
||||
SAFE_CALL(rename_file, index, String::toStdString(fsutils::toNativePath(name)));
|
||||
SAFE_CALL(rename_file, index, Utils::String::toStdString(Utils::Fs::toNativePath(name)));
|
||||
}
|
||||
|
||||
bool TorrentHandle::saveTorrentFile(const QString &path)
|
||||
@@ -1307,7 +1307,7 @@ void TorrentHandle::handleStorageMovedAlert(libtorrent::storage_moved_alert *p)
|
||||
return;
|
||||
}
|
||||
|
||||
QString newPath = String::fromStdString(p->path);
|
||||
QString newPath = Utils::String::fromStdString(p->path);
|
||||
if (newPath != m_newPath) {
|
||||
qWarning("TorrentHandleImpl::handleStorageMoved(): New path doesn't match a path in a queue.");
|
||||
return;
|
||||
@@ -1328,7 +1328,7 @@ void TorrentHandle::handleStorageMovedAlert(libtorrent::storage_moved_alert *p)
|
||||
}
|
||||
|
||||
// Attempt to remove old folder if empty
|
||||
QDir oldSaveDir(fsutils::fromNativePath(m_oldPath));
|
||||
QDir oldSaveDir(Utils::Fs::fromNativePath(m_oldPath));
|
||||
if ((oldSaveDir != QDir(m_session->defaultSavePath())) && (oldSaveDir != QDir(m_session->tempPath()))) {
|
||||
qDebug("Attempting to remove %s", qPrintable(m_oldPath));
|
||||
QDir().rmpath(m_oldPath);
|
||||
@@ -1348,7 +1348,7 @@ void TorrentHandle::handleStorageMovedFailedAlert(libtorrent::storage_moved_fail
|
||||
}
|
||||
|
||||
Logger::instance()->addMessage(tr("Could not move torrent: '%1'. Reason: %2")
|
||||
.arg(name()).arg(String::fromStdString(p->message())), Log::CRITICAL);
|
||||
.arg(name()).arg(Utils::String::fromStdString(p->message())), Log::CRITICAL);
|
||||
|
||||
m_newPath.clear();
|
||||
if (!m_queuedPath.isEmpty()) {
|
||||
@@ -1364,7 +1364,7 @@ void TorrentHandle::handleStorageMovedFailedAlert(libtorrent::storage_moved_fail
|
||||
|
||||
void TorrentHandle::handleTrackerReplyAlert(libtorrent::tracker_reply_alert *p)
|
||||
{
|
||||
QString trackerUrl = String::fromStdString(p->url);
|
||||
QString trackerUrl = Utils::String::fromStdString(p->url);
|
||||
qDebug("Received a tracker reply from %s (Num_peers = %d)", qPrintable(trackerUrl), p->num_peers);
|
||||
// Connection was successful now. Remove possible old errors
|
||||
m_trackerInfos[trackerUrl].lastMessage.clear(); // Reset error/warning message
|
||||
@@ -1375,8 +1375,8 @@ void TorrentHandle::handleTrackerReplyAlert(libtorrent::tracker_reply_alert *p)
|
||||
|
||||
void TorrentHandle::handleTrackerWarningAlert(libtorrent::tracker_warning_alert *p)
|
||||
{
|
||||
QString trackerUrl = String::fromStdString(p->url);
|
||||
QString message = String::fromStdString(p->msg);
|
||||
QString trackerUrl = Utils::String::fromStdString(p->url);
|
||||
QString message = Utils::String::fromStdString(p->msg);
|
||||
qDebug("Received a tracker warning for %s: %s", qPrintable(trackerUrl), qPrintable(message));
|
||||
// Connection was successful now but there is a warning message
|
||||
m_trackerInfos[trackerUrl].lastMessage = message; // Store warning message
|
||||
@@ -1386,8 +1386,8 @@ void TorrentHandle::handleTrackerWarningAlert(libtorrent::tracker_warning_alert
|
||||
|
||||
void TorrentHandle::handleTrackerErrorAlert(libtorrent::tracker_error_alert *p)
|
||||
{
|
||||
QString trackerUrl = String::fromStdString(p->url);
|
||||
QString message = String::fromStdString(p->msg);
|
||||
QString trackerUrl = Utils::String::fromStdString(p->url);
|
||||
QString message = Utils::String::fromStdString(p->msg);
|
||||
qDebug("Received a tracker error for %s: %s", qPrintable(trackerUrl), qPrintable(message));
|
||||
m_trackerInfos[trackerUrl].lastMessage = message;
|
||||
|
||||
@@ -1487,13 +1487,13 @@ void TorrentHandle::handleFastResumeRejectedAlert(libtorrent::fastresume_rejecte
|
||||
}
|
||||
else {
|
||||
logger->addMessage(tr("Fast resume data was rejected for torrent %1. Reason: %2. Checking again...")
|
||||
.arg(name()).arg(String::fromStdString(p->message())), Log::CRITICAL);
|
||||
.arg(name()).arg(Utils::String::fromStdString(p->message())), Log::CRITICAL);
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentHandle::handleFileRenamedAlert(libtorrent::file_renamed_alert *p)
|
||||
{
|
||||
QString newName = fsutils::fromNativePath(String::fromStdString(p->name));
|
||||
QString newName = Utils::Fs::fromNativePath(Utils::String::fromStdString(p->name));
|
||||
|
||||
// TODO: Check this!
|
||||
if (filesCount() > 1) {
|
||||
@@ -1573,7 +1573,7 @@ void TorrentHandle::adjustSavePath()
|
||||
QString defaultSavePath = m_session->defaultSavePath();
|
||||
if (m_session->useAppendLabelToSavePath() && !m_label.isEmpty())
|
||||
defaultSavePath += QString("%1/").arg(m_label);
|
||||
defaultSavePath = fsutils::toNativePath(defaultSavePath);
|
||||
defaultSavePath = Utils::Fs::toNativePath(defaultSavePath);
|
||||
if (m_savePath != defaultSavePath) {
|
||||
if (!useTempPath()) {
|
||||
moveStorage(defaultSavePath);
|
||||
@@ -1702,7 +1702,7 @@ void TorrentHandle::adjustActualSavePath()
|
||||
qDebug("Moving torrent to its temp save path: %s", qPrintable(path));
|
||||
}
|
||||
|
||||
moveStorage(fsutils::toNativePath(path));
|
||||
moveStorage(Utils::Fs::toNativePath(path));
|
||||
}
|
||||
|
||||
libtorrent::torrent_handle TorrentHandle::nativeHandle() const
|
||||
@@ -1764,8 +1764,8 @@ void TorrentHandle::updateStatus(const libtorrent::torrent_status &nativeStatus)
|
||||
m_nativeStatus = nativeStatus;
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
try {
|
||||
m_nativeName = String::fromStdString(m_nativeHandle.name());
|
||||
m_nativeSavePath = fsutils::fromNativePath(String::fromStdString(m_nativeHandle.save_path()));
|
||||
m_nativeName = Utils::String::fromStdString(m_nativeHandle.name());
|
||||
m_nativeSavePath = Utils::Fs::fromNativePath(Utils::String::fromStdString(m_nativeHandle.save_path()));
|
||||
}
|
||||
catch (std::exception &exc) {
|
||||
qDebug("torrent_handle method inside TorrentHandleImpl::updateStatus() throws exception: %s", exc.what());
|
||||
@@ -1835,11 +1835,11 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
||||
// Move unwanted files to a .unwanted subfolder
|
||||
if (priorities[i] == 0) {
|
||||
QString oldAbsPath = QDir(spath).absoluteFilePath(filepath);
|
||||
QString parentAbsPath = fsutils::branchPath(oldAbsPath);
|
||||
QString parentAbsPath = Utils::Fs::branchPath(oldAbsPath);
|
||||
// Make sure the file does not already exists
|
||||
if (QDir(parentAbsPath).dirName() != ".unwanted") {
|
||||
QString unwantedAbsPath = parentAbsPath + "/.unwanted";
|
||||
QString newAbsPath = unwantedAbsPath + "/" + fsutils::fileName(filepath);
|
||||
QString newAbsPath = unwantedAbsPath + "/" + Utils::Fs::fileName(filepath);
|
||||
qDebug() << "Unwanted path is" << unwantedAbsPath;
|
||||
if (QFile::exists(newAbsPath)) {
|
||||
qWarning() << "File" << newAbsPath << "already exists at destination.";
|
||||
@@ -1852,25 +1852,25 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
||||
if (created) {
|
||||
// Hide the folder on Windows
|
||||
qDebug() << "Hiding folder (Windows)";
|
||||
std::wstring winPath = fsutils::toNativePath(unwantedAbsPath).toStdWString();
|
||||
std::wstring winPath = Utils::Fs::toNativePath(unwantedAbsPath).toStdWString();
|
||||
DWORD dwAttrs = ::GetFileAttributesW(winPath.c_str());
|
||||
bool ret = ::SetFileAttributesW(winPath.c_str(), dwAttrs | FILE_ATTRIBUTE_HIDDEN);
|
||||
Q_ASSERT(ret != 0); Q_UNUSED(ret);
|
||||
}
|
||||
#endif
|
||||
QString parentPath = fsutils::branchPath(filepath);
|
||||
QString parentPath = Utils::Fs::branchPath(filepath);
|
||||
if (!parentPath.isEmpty() && !parentPath.endsWith("/"))
|
||||
parentPath += "/";
|
||||
renameFile(i, parentPath + ".unwanted/" + fsutils::fileName(filepath));
|
||||
renameFile(i, parentPath + ".unwanted/" + Utils::Fs::fileName(filepath));
|
||||
}
|
||||
}
|
||||
|
||||
// Move wanted files back to their original folder
|
||||
if (priorities[i] > 0) {
|
||||
QString parentRelPath = fsutils::branchPath(filepath);
|
||||
QString parentRelPath = Utils::Fs::branchPath(filepath);
|
||||
if (QDir(parentRelPath).dirName() == ".unwanted") {
|
||||
QString oldName = fsutils::fileName(filepath);
|
||||
QString newRelPath = fsutils::branchPath(parentRelPath);
|
||||
QString oldName = Utils::Fs::fileName(filepath);
|
||||
QString newRelPath = Utils::Fs::branchPath(parentRelPath);
|
||||
if (newRelPath.isEmpty())
|
||||
renameFile(i, oldName);
|
||||
else
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <libtorrent/error_code.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
#include "core/misc.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/utils/misc.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "infohash.h"
|
||||
#include "trackerentry.h"
|
||||
@@ -64,7 +64,7 @@ TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString &error)
|
||||
{
|
||||
error.clear();
|
||||
libt::error_code ec;
|
||||
TorrentInfo info(new libt::torrent_info(String::toStdString(fsutils::toNativePath(path)), ec));
|
||||
TorrentInfo info(new libt::torrent_info(Utils::String::toStdString(Utils::Fs::toNativePath(path)), ec));
|
||||
if (ec) {
|
||||
error = QString::fromUtf8(ec.message().c_str());
|
||||
qDebug("Cannot load .torrent file: %s", qPrintable(error));
|
||||
@@ -93,7 +93,7 @@ InfoHash TorrentInfo::hash() const
|
||||
QString TorrentInfo::name() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(m_nativeInfo->name());
|
||||
return Utils::String::fromStdString(m_nativeInfo->name());
|
||||
}
|
||||
|
||||
QDateTime TorrentInfo::creationDate() const
|
||||
@@ -106,13 +106,13 @@ QDateTime TorrentInfo::creationDate() const
|
||||
QString TorrentInfo::creator() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(m_nativeInfo->creator());
|
||||
return Utils::String::fromStdString(m_nativeInfo->creator());
|
||||
}
|
||||
|
||||
QString TorrentInfo::comment() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(m_nativeInfo->comment());
|
||||
return Utils::String::fromStdString(m_nativeInfo->comment());
|
||||
}
|
||||
|
||||
bool TorrentInfo::isPrivate() const
|
||||
@@ -148,7 +148,7 @@ int TorrentInfo::piecesCount() const
|
||||
QString TorrentInfo::filePath(int index) const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return fsutils::fromNativePath(String::fromStdString(m_nativeInfo->files().file_path(index)));
|
||||
return Utils::Fs::fromNativePath(Utils::String::fromStdString(m_nativeInfo->files().file_path(index)));
|
||||
}
|
||||
|
||||
QStringList TorrentInfo::filePaths() const
|
||||
@@ -162,13 +162,13 @@ QStringList TorrentInfo::filePaths() const
|
||||
|
||||
QString TorrentInfo::fileName(int index) const
|
||||
{
|
||||
return fsutils::fileName(filePath(index));
|
||||
return Utils::Fs::fileName(filePath(index));
|
||||
}
|
||||
|
||||
QString TorrentInfo::origFilePath(int index) const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return fsutils::fromNativePath(String::fromStdString(m_nativeInfo->orig_files().file_path(index)));
|
||||
return Utils::Fs::fromNativePath(Utils::String::fromStdString(m_nativeInfo->orig_files().file_path(index)));
|
||||
}
|
||||
|
||||
qlonglong TorrentInfo::fileSize(int index) const
|
||||
@@ -215,13 +215,13 @@ QByteArray TorrentInfo::metadata() const
|
||||
QString TorrentInfo::toMagnetUri() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(libt::make_magnet_uri(*m_nativeInfo));
|
||||
return Utils::String::fromStdString(libt::make_magnet_uri(*m_nativeInfo));
|
||||
}
|
||||
|
||||
void TorrentInfo::renameFile(uint index, const QString &newPath)
|
||||
{
|
||||
if (!isValid()) return;
|
||||
m_nativeInfo->rename_file(index, String::toStdString(newPath));
|
||||
m_nativeInfo->rename_file(index, Utils::String::toStdString(newPath));
|
||||
}
|
||||
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> TorrentInfo::nativeInfo() const
|
||||
|
||||
@@ -65,8 +65,8 @@ libtorrent::entry Peer::toEntry(bool noPeerId) const
|
||||
{
|
||||
libtorrent::entry::dictionary_type peerMap;
|
||||
if (!noPeerId)
|
||||
peerMap["id"] = libtorrent::entry(String::toStdString(peerId));
|
||||
peerMap["ip"] = libtorrent::entry(String::toStdString(ip));
|
||||
peerMap["id"] = libtorrent::entry(Utils::String::toStdString(peerId));
|
||||
peerMap["ip"] = libtorrent::entry(Utils::String::toStdString(ip));
|
||||
peerMap["port"] = libtorrent::entry(port);
|
||||
|
||||
return libtorrent::entry(peerMap);
|
||||
|
||||
@@ -28,14 +28,14 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "core/misc.h"
|
||||
#include "core/utils/misc.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
TrackerEntry::TrackerEntry(const QString &url)
|
||||
: m_nativeEntry(libtorrent::announce_entry(String::toStdString(url)))
|
||||
: m_nativeEntry(libtorrent::announce_entry(Utils::String::toStdString(url)))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ TrackerEntry::TrackerEntry(const TrackerEntry &other)
|
||||
|
||||
QString TrackerEntry::url() const
|
||||
{
|
||||
return String::fromStdString(m_nativeEntry.url);
|
||||
return Utils::String::fromStdString(m_nativeEntry.url);
|
||||
}
|
||||
|
||||
int TrackerEntry::tier() const
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
HEADERS += \
|
||||
$$PWD/types.h \
|
||||
$$PWD/misc.h \
|
||||
$$PWD/fs_utils.h \
|
||||
$$PWD/tristatebool.h \
|
||||
$$PWD/filesystemwatcher.h \
|
||||
$$PWD/qinisettings.h \
|
||||
@@ -38,13 +36,13 @@ HEADERS += \
|
||||
$$PWD/bittorrent/private/bandwidthscheduler.h \
|
||||
$$PWD/bittorrent/private/filterparserthread.h \
|
||||
$$PWD/bittorrent/private/statistics.h \
|
||||
$$PWD/utils/fs.h \
|
||||
$$PWD/utils/misc.h \
|
||||
$$PWD/utils/string.h \
|
||||
$$PWD/torrentfilter.h \
|
||||
$$PWD/scanfoldersmodel.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/misc.cpp \
|
||||
$$PWD/fs_utils.cpp \
|
||||
$$PWD/tristatebool.cpp \
|
||||
$$PWD/filesystemwatcher.cpp \
|
||||
$$PWD/logger.cpp \
|
||||
@@ -76,6 +74,8 @@ SOURCES += \
|
||||
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
|
||||
$$PWD/bittorrent/private/filterparserthread.cpp \
|
||||
$$PWD/bittorrent/private/statistics.cpp \
|
||||
$$PWD/utils/fs.cpp \
|
||||
$$PWD/utils/misc.cpp \
|
||||
$$PWD/utils/string.cpp \
|
||||
$$PWD/torrentfilter.cpp \
|
||||
$$PWD/scanfoldersmodel.cpp
|
||||
|
||||
@@ -1,475 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
#include <QCoreApplication>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#elif defined(Q_OS_HAIKU)
|
||||
#include <kernel/fs_info.h>
|
||||
#else
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
#else
|
||||
#include <shlobj.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
#include <QDesktopServices>
|
||||
#else
|
||||
#include <QStandardPaths>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
/**
|
||||
* Converts a path to a string suitable for display.
|
||||
* This function makes sure the directory separator used is consistent
|
||||
* with the OS being run.
|
||||
*/
|
||||
QString fsutils::toNativePath(const QString& path) {
|
||||
return QDir::toNativeSeparators(path);
|
||||
}
|
||||
|
||||
QString fsutils::fromNativePath(const QString &path) {
|
||||
return QDir::fromNativeSeparators(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file extension part of a file name.
|
||||
*/
|
||||
QString fsutils::fileExtension(const QString &filename) {
|
||||
QString ext = QString(filename).remove(".!qB");
|
||||
const int point_index = ext.lastIndexOf(".");
|
||||
return (point_index >= 0) ? ext.mid(point_index + 1) : QString();
|
||||
}
|
||||
|
||||
QString fsutils::fileName(const QString& file_path) {
|
||||
QString path = fsutils::fromNativePath(file_path);
|
||||
const int slash_index = path.lastIndexOf("/");
|
||||
if (slash_index == -1)
|
||||
return path;
|
||||
return path.mid(slash_index + 1);
|
||||
}
|
||||
|
||||
QString fsutils::folderName(const QString& file_path) {
|
||||
QString path = fsutils::fromNativePath(file_path);
|
||||
const int slash_index = path.lastIndexOf("/");
|
||||
if (slash_index == -1)
|
||||
return path;
|
||||
return path.left(slash_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an empty folder tree.
|
||||
*
|
||||
* This function will also remove .DS_Store files on Mac OS and
|
||||
* Thumbs.db on Windows.
|
||||
*/
|
||||
bool fsutils::smartRemoveEmptyFolderTree(const QString& dir_path) {
|
||||
qDebug() << Q_FUNC_INFO << dir_path;
|
||||
if (dir_path.isEmpty())
|
||||
return false;
|
||||
|
||||
QDir dir(dir_path);
|
||||
if (!dir.exists())
|
||||
return true;
|
||||
|
||||
// Remove Files created by the OS
|
||||
#if defined Q_OS_MAC
|
||||
fsutils::forceRemove(dir_path + QLatin1String("/.DS_Store"));
|
||||
#elif defined Q_OS_WIN
|
||||
fsutils::forceRemove(dir_path + QLatin1String("/Thumbs.db"));
|
||||
#endif
|
||||
|
||||
QFileInfoList sub_files = dir.entryInfoList();
|
||||
foreach (const QFileInfo& info, sub_files) {
|
||||
QString sub_name = info.fileName();
|
||||
if (sub_name == "." || sub_name == "..")
|
||||
continue;
|
||||
|
||||
QString sub_path = info.absoluteFilePath();
|
||||
qDebug() << Q_FUNC_INFO << "sub file: " << sub_path;
|
||||
if (info.isDir()) {
|
||||
if (!smartRemoveEmptyFolderTree(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove folder: " << sub_path;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (info.isHidden()) {
|
||||
qDebug() << Q_FUNC_INFO << "Removing hidden file: " << sub_path;
|
||||
if (!fsutils::forceRemove(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove " << sub_path;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "Folder is not empty, aborting. Found: " << sub_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << "Calling rmdir on " << dir_path;
|
||||
return QDir().rmdir(dir_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the file with the given file_path.
|
||||
*
|
||||
* This function will try to fix the file permissions before removing it.
|
||||
*/
|
||||
bool fsutils::forceRemove(const QString& file_path) {
|
||||
QFile f(file_path);
|
||||
if (!f.exists())
|
||||
return true;
|
||||
// Make sure we have read/write permissions
|
||||
f.setPermissions(f.permissions()|QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser);
|
||||
// Remove the file
|
||||
return f.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of a file.
|
||||
* If the file is a folder, it will compute its size based on its content.
|
||||
*
|
||||
* Returns -1 in case of error.
|
||||
*/
|
||||
qint64 fsutils::computePathSize(const QString& path) {
|
||||
// Check if it is a file
|
||||
QFileInfo fi(path);
|
||||
if (!fi.exists()) return -1;
|
||||
if (fi.isFile()) return fi.size();
|
||||
// Compute folder size based on its content
|
||||
qint64 size = 0;
|
||||
foreach (const QFileInfo &subfi, QDir(path).entryInfoList(QDir::Dirs|QDir::Files)) {
|
||||
if (subfi.fileName().startsWith(".")) continue;
|
||||
if (subfi.isDir())
|
||||
size += fsutils::computePathSize(subfi.absoluteFilePath());
|
||||
else
|
||||
size += subfi.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes deep comparison of two files to make sure they are identical.
|
||||
*/
|
||||
bool fsutils::sameFiles(const QString& path1, const QString& path2) {
|
||||
QFile f1(path1), f2(path2);
|
||||
if (!f1.exists() || !f2.exists()) return false;
|
||||
if (f1.size() != f2.size()) return false;
|
||||
if (!f1.open(QIODevice::ReadOnly)) return false;
|
||||
if (!f2.open(QIODevice::ReadOnly)) {
|
||||
f1.close();
|
||||
return false;
|
||||
}
|
||||
bool same = true;
|
||||
while(!f1.atEnd() && !f2.atEnd()) {
|
||||
if (f1.read(1024) != f2.read(1024)) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
f1.close(); f2.close();
|
||||
return same;
|
||||
}
|
||||
|
||||
QString fsutils::toValidFileSystemName(QString filename) {
|
||||
qDebug("toValidFSName: %s", qPrintable(filename));
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
filename.replace(regex, " ");
|
||||
qDebug("toValidFSName, result: %s", qPrintable(filename));
|
||||
return filename.trimmed();
|
||||
}
|
||||
|
||||
bool fsutils::isValidFileSystemName(const QString& filename) {
|
||||
if (filename.isEmpty()) return false;
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
return !filename.contains(regex);
|
||||
}
|
||||
|
||||
long long fsutils::freeDiskSpaceOnPath(QString path) {
|
||||
if (path.isEmpty()) return -1;
|
||||
QDir dir_path(path);
|
||||
if (!dir_path.exists()) {
|
||||
QStringList parts = path.split("/");
|
||||
while (parts.size() > 1 && !QDir(parts.join("/")).exists()) {
|
||||
parts.removeLast();
|
||||
}
|
||||
dir_path = QDir(parts.join("/"));
|
||||
if (!dir_path.exists()) return -1;
|
||||
}
|
||||
Q_ASSERT(dir_path.exists());
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
unsigned long long available;
|
||||
#ifdef Q_OS_HAIKU
|
||||
const QString statfs_path = dir_path.path()+"/.";
|
||||
dev_t device = dev_for_path (qPrintable(statfs_path));
|
||||
if (device >= 0) {
|
||||
fs_info info;
|
||||
if(fs_stat_dev(device, &info)==B_OK){
|
||||
available = ((unsigned long long)(info.free_blocks*info.block_size));
|
||||
return available;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
struct statfs stats;
|
||||
const QString statfs_path = dir_path.path()+"/.";
|
||||
const int ret = statfs (qPrintable(statfs_path), &stats) ;
|
||||
if (ret == 0) {
|
||||
available = ((unsigned long long)stats.f_bavail) *
|
||||
((unsigned long long)stats.f_bsize) ;
|
||||
return available;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER);
|
||||
GetDiskFreeSpaceEx_t
|
||||
pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress
|
||||
(
|
||||
::GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetDiskFreeSpaceExW"
|
||||
);
|
||||
if ( pGetDiskFreeSpaceEx )
|
||||
{
|
||||
ULARGE_INTEGER bytesFree, bytesTotal;
|
||||
unsigned long long *ret;
|
||||
if (pGetDiskFreeSpaceEx((LPCTSTR)(fsutils::toNativePath(dir_path.path())).utf16(), &bytesFree, &bytesTotal, NULL)) {
|
||||
ret = (unsigned long long*)&bytesFree;
|
||||
return *ret;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::branchPath(const QString& file_path, QString* removed) {
|
||||
QString ret = fsutils::fromNativePath(file_path);
|
||||
if (ret.endsWith("/"))
|
||||
ret.chop(1);
|
||||
const int slashIndex = ret.lastIndexOf("/");
|
||||
if (slashIndex >= 0) {
|
||||
if (removed)
|
||||
*removed = ret.mid(slashIndex + 1);
|
||||
ret = ret.left(slashIndex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool fsutils::sameFileNames(const QString &first, const QString &second) {
|
||||
#if defined(Q_OS_UNIX) || defined(Q_WS_QWS)
|
||||
return QString::compare(first, second, Qt::CaseSensitive) == 0;
|
||||
#else
|
||||
return QString::compare(first, second, Qt::CaseInsensitive) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
QString fsutils::expandPath(const QString &path) {
|
||||
QString ret = fsutils::fromNativePath(path.trimmed());
|
||||
if (ret.isEmpty())
|
||||
return ret;
|
||||
|
||||
return QDir::cleanPath(ret);
|
||||
}
|
||||
|
||||
QString fsutils::expandPathAbs(const QString& path) {
|
||||
QString ret = fsutils::expandPath(path);
|
||||
|
||||
if (!QDir::isAbsolutePath(ret))
|
||||
ret = QDir(ret).absolutePath();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesDataLocation() {
|
||||
QString result;
|
||||
#ifdef Q_OS_WIN
|
||||
LPWSTR path=new WCHAR[256];
|
||||
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
||||
result = fsutils::fromNativePath(QString::fromWCharArray(path));
|
||||
if (!QCoreApplication::applicationName().isEmpty())
|
||||
result += QLatin1String("/") + qApp->applicationName();
|
||||
#else
|
||||
#ifdef Q_OS_MAC
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QString path;
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
result += QLatin1Char('/') + qApp->applicationName();
|
||||
#else
|
||||
QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
|
||||
if (xdgDataHome.isEmpty())
|
||||
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
|
||||
xdgDataHome += QLatin1String("/data/")
|
||||
+ qApp->applicationName();
|
||||
result = xdgDataHome;
|
||||
#endif
|
||||
#endif
|
||||
if (!result.endsWith("/"))
|
||||
result += "/";
|
||||
return result;
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesCacheLocation() {
|
||||
QString result;
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||
result = QDesktopServicesDataLocation() + QLatin1String("cache");
|
||||
#else
|
||||
#ifdef Q_OS_MAC
|
||||
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kCachedDataFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
result += QLatin1Char('/') + qApp->applicationName();
|
||||
#else
|
||||
QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
|
||||
if (xdgCacheHome.isEmpty())
|
||||
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
|
||||
xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
|
||||
result = xdgCacheHome;
|
||||
#endif
|
||||
#endif
|
||||
if (!result.endsWith("/"))
|
||||
result += "/";
|
||||
return result;
|
||||
}
|
||||
|
||||
QString fsutils::QDesktopServicesDownloadLocation() {
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||
// as long as it stays WinXP like we do the same on OS/2
|
||||
// TODO: Use IKnownFolderManager to get path of FOLDERID_Downloads
|
||||
// instead of hardcoding "Downloads"
|
||||
// Unfortunately, this would break compatibility with WinXP
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
return QDir(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)).absoluteFilePath(
|
||||
QCoreApplication::translate("fsutils", "Downloads"));
|
||||
#else
|
||||
return QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).absoluteFilePath(
|
||||
QCoreApplication::translate("fsutils", "Downloads"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
QString save_path;
|
||||
// Default save path on Linux
|
||||
QString config_path = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME").constData());
|
||||
if (config_path.isEmpty())
|
||||
config_path = QDir::home().absoluteFilePath(".config");
|
||||
|
||||
QString user_dirs_file = config_path + "/user-dirs.dirs";
|
||||
if (QFile::exists(user_dirs_file)) {
|
||||
QSettings settings(user_dirs_file, QSettings::IniFormat);
|
||||
// We need to force UTF-8 encoding here since this is not
|
||||
// the default for Ini files.
|
||||
settings.setIniCodec("UTF-8");
|
||||
QString xdg_download_dir = settings.value("XDG_DOWNLOAD_DIR").toString();
|
||||
if (!xdg_download_dir.isEmpty()) {
|
||||
// Resolve $HOME environment variables
|
||||
xdg_download_dir.replace("$HOME", QDir::homePath());
|
||||
save_path = xdg_download_dir;
|
||||
qDebug() << Q_FUNC_INFO << "SUCCESS: Using XDG path for downloads: " << save_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
if (!save_path.isEmpty() && !QFile::exists(save_path)) {
|
||||
QDir().mkpath(save_path);
|
||||
}
|
||||
|
||||
if (save_path.isEmpty() || !QFile::exists(save_path)) {
|
||||
save_path = QDir::home().absoluteFilePath(QCoreApplication::translate("fsutils", "Downloads"));
|
||||
qDebug() << Q_FUNC_INFO << "using" << save_path << "as fallback since the XDG detection did not work";
|
||||
}
|
||||
|
||||
return save_path;
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// TODO: How to support this on Mac OS X?
|
||||
#endif
|
||||
|
||||
// Fallback
|
||||
return QDir::home().absoluteFilePath(QCoreApplication::translate("fsutils", "Downloads"));
|
||||
}
|
||||
|
||||
QString fsutils::searchEngineLocation() {
|
||||
QString folder = "nova";
|
||||
if (misc::pythonVersion() >= 3)
|
||||
folder = "nova3";
|
||||
const QString location = fsutils::expandPathAbs(QDesktopServicesDataLocation()
|
||||
+ folder);
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
|
||||
QString fsutils::cacheLocation() {
|
||||
QString location = fsutils::expandPathAbs(QDesktopServicesCacheLocation());
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
@@ -38,8 +38,8 @@
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/misc.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "downloadhandler.h"
|
||||
|
||||
@@ -108,7 +108,7 @@ void DownloadHandler::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
||||
// Total number of bytes is available
|
||||
if (bytesTotal > m_sizeLimit) {
|
||||
m_reply->abort();
|
||||
emit downloadFailed(m_url, msg.arg(misc::friendlyUnit(bytesTotal)).arg(misc::friendlyUnit(m_sizeLimit)));
|
||||
emit downloadFailed(m_url, msg.arg(Utils::Misc::friendlyUnit(bytesTotal)).arg(Utils::Misc::friendlyUnit(m_sizeLimit)));
|
||||
}
|
||||
else {
|
||||
disconnect(m_reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(checkDownloadSize(qint64, qint64)));
|
||||
@@ -116,7 +116,7 @@ void DownloadHandler::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal)
|
||||
}
|
||||
else if (bytesReceived > m_sizeLimit) {
|
||||
m_reply->abort();
|
||||
emit downloadFailed(m_url, msg.arg(misc::friendlyUnit(bytesReceived)).arg(misc::friendlyUnit(m_sizeLimit)));
|
||||
emit downloadFailed(m_url, msg.arg(Utils::Misc::friendlyUnit(bytesReceived)).arg(Utils::Misc::friendlyUnit(m_sizeLimit)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ bool DownloadHandler::saveToFile(QString &filePath)
|
||||
}
|
||||
else {
|
||||
delete tmpfile;
|
||||
fsutils::forceRemove(filePath);
|
||||
Utils::Fs::forceRemove(filePath);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
#include <winreg.h>
|
||||
#endif
|
||||
|
||||
#include "misc.h"
|
||||
#include "fs_utils.h"
|
||||
#include "core/utils/fs.h"
|
||||
#include "core/utils/misc.h"
|
||||
|
||||
|
||||
Preferences* Preferences::m_instance = 0;
|
||||
@@ -169,7 +169,7 @@ bool Preferences::save()
|
||||
QString final_path = new_path;
|
||||
int index = final_path.lastIndexOf("_new", -1, Qt::CaseInsensitive);
|
||||
final_path.remove(index, 4);
|
||||
fsutils::forceRemove(final_path);
|
||||
Utils::Fs::forceRemove(final_path);
|
||||
QFile::rename(new_path, final_path);
|
||||
#else
|
||||
delete settings;
|
||||
@@ -347,7 +347,7 @@ void Preferences::setWinStartup(bool b)
|
||||
{
|
||||
QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
|
||||
if (b) {
|
||||
const QString bin_path = "\"" + fsutils::toNativePath(qApp->applicationFilePath()) + "\"";
|
||||
const QString bin_path = "\"" + Utils::Fs::toNativePath(qApp->applicationFilePath()) + "\"";
|
||||
settings.setValue("qBittorrent", bin_path);
|
||||
}
|
||||
else {
|
||||
@@ -361,13 +361,13 @@ QString Preferences::getSavePath() const
|
||||
{
|
||||
QString save_path = value("Preferences/Downloads/SavePath").toString();
|
||||
if (!save_path.isEmpty())
|
||||
return fsutils::fromNativePath(save_path);
|
||||
return fsutils::QDesktopServicesDownloadLocation();
|
||||
return Utils::Fs::fromNativePath(save_path);
|
||||
return Utils::Fs::QDesktopServicesDownloadLocation();
|
||||
}
|
||||
|
||||
void Preferences::setSavePath(const QString &save_path)
|
||||
{
|
||||
setValue("Preferences/Downloads/SavePath", fsutils::fromNativePath(save_path));
|
||||
setValue("Preferences/Downloads/SavePath", Utils::Fs::fromNativePath(save_path));
|
||||
}
|
||||
|
||||
bool Preferences::isTempPathEnabled() const
|
||||
@@ -383,12 +383,12 @@ void Preferences::setTempPathEnabled(bool enabled)
|
||||
QString Preferences::getTempPath() const
|
||||
{
|
||||
const QString temp = QDir(getSavePath()).absoluteFilePath("temp");
|
||||
return fsutils::fromNativePath(value("Preferences/Downloads/TempPath", temp).toString());
|
||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/TempPath", temp).toString());
|
||||
}
|
||||
|
||||
void Preferences::setTempPath(const QString &path)
|
||||
{
|
||||
setValue("Preferences/Downloads/TempPath", fsutils::fromNativePath(path));
|
||||
setValue("Preferences/Downloads/TempPath", Utils::Fs::fromNativePath(path));
|
||||
}
|
||||
|
||||
bool Preferences::useIncompleteFilesExtension() const
|
||||
@@ -413,12 +413,12 @@ void Preferences::setAppendTorrentLabel(bool b)
|
||||
|
||||
QString Preferences::lastLocationPath() const
|
||||
{
|
||||
return fsutils::fromNativePath(value("Preferences/Downloads/LastLocationPath").toString());
|
||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/LastLocationPath").toString());
|
||||
}
|
||||
|
||||
void Preferences::setLastLocationPath(const QString &path)
|
||||
{
|
||||
setValue("Preferences/Downloads/LastLocationPath", fsutils::fromNativePath(path));
|
||||
setValue("Preferences/Downloads/LastLocationPath", Utils::Fs::fromNativePath(path));
|
||||
}
|
||||
|
||||
bool Preferences::preAllocateAllFiles() const
|
||||
@@ -469,7 +469,7 @@ QStringList Preferences::getScanDirs() const
|
||||
|
||||
QStringList newList;
|
||||
foreach (const QString& s, originalList)
|
||||
newList << fsutils::fromNativePath(s);
|
||||
newList << Utils::Fs::fromNativePath(s);
|
||||
return newList;
|
||||
}
|
||||
|
||||
@@ -479,28 +479,28 @@ void Preferences::setScanDirs(const QStringList &dirs)
|
||||
QStringList newList;
|
||||
if (!dirs.isEmpty())
|
||||
foreach (const QString& s, dirs)
|
||||
newList << fsutils::fromNativePath(s);
|
||||
newList << Utils::Fs::fromNativePath(s);
|
||||
setValue("Preferences/Downloads/ScanDirs", newList);
|
||||
}
|
||||
|
||||
QList<bool> Preferences::getDownloadInScanDirs() const
|
||||
{
|
||||
return misc::boolListfromStringList(value("Preferences/Downloads/DownloadInScanDirs").toStringList());
|
||||
return Utils::Misc::boolListfromStringList(value("Preferences/Downloads/DownloadInScanDirs").toStringList());
|
||||
}
|
||||
|
||||
void Preferences::setDownloadInScanDirs(const QList<bool> &list)
|
||||
{
|
||||
setValue("Preferences/Downloads/DownloadInScanDirs", misc::toStringList(list));
|
||||
setValue("Preferences/Downloads/DownloadInScanDirs", Utils::Misc::toStringList(list));
|
||||
}
|
||||
|
||||
QString Preferences::getScanDirsLastPath() const
|
||||
{
|
||||
return fsutils::fromNativePath(value("Preferences/Downloads/ScanDirsLastPath").toString());
|
||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/ScanDirsLastPath").toString());
|
||||
}
|
||||
|
||||
void Preferences::setScanDirsLastPath(const QString &path)
|
||||
{
|
||||
setValue("Preferences/Downloads/ScanDirsLastPath", fsutils::fromNativePath(path));
|
||||
setValue("Preferences/Downloads/ScanDirsLastPath", Utils::Fs::fromNativePath(path));
|
||||
}
|
||||
|
||||
bool Preferences::isTorrentExportEnabled() const
|
||||
@@ -510,12 +510,12 @@ bool Preferences::isTorrentExportEnabled() const
|
||||
|
||||
QString Preferences::getTorrentExportDir() const
|
||||
{
|
||||
return fsutils::fromNativePath(value("Preferences/Downloads/TorrentExportDir").toString());
|
||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/TorrentExportDir").toString());
|
||||
}
|
||||
|
||||
void Preferences::setTorrentExportDir(QString path)
|
||||
{
|
||||
setValue("Preferences/Downloads/TorrentExportDir", fsutils::fromNativePath(path.trimmed()));
|
||||
setValue("Preferences/Downloads/TorrentExportDir", Utils::Fs::fromNativePath(path.trimmed()));
|
||||
}
|
||||
|
||||
bool Preferences::isFinishedTorrentExportEnabled() const
|
||||
@@ -525,12 +525,12 @@ bool Preferences::isFinishedTorrentExportEnabled() const
|
||||
|
||||
QString Preferences::getFinishedTorrentExportDir() const
|
||||
{
|
||||
return fsutils::fromNativePath(value("Preferences/Downloads/FinishedTorrentExportDir").toString());
|
||||
return Utils::Fs::fromNativePath(value("Preferences/Downloads/FinishedTorrentExportDir").toString());
|
||||
}
|
||||
|
||||
void Preferences::setFinishedTorrentExportDir(QString path)
|
||||
{
|
||||
setValue("Preferences/Downloads/FinishedTorrentExportDir", fsutils::fromNativePath(path.trimmed()));
|
||||
setValue("Preferences/Downloads/FinishedTorrentExportDir", Utils::Fs::fromNativePath(path.trimmed()));
|
||||
}
|
||||
|
||||
bool Preferences::isMailNotificationEnabled() const
|
||||
@@ -975,12 +975,12 @@ void Preferences::setFilteringEnabled(bool enabled)
|
||||
|
||||
QString Preferences::getFilter() const
|
||||
{
|
||||
return fsutils::fromNativePath(value("Preferences/IPFilter/File").toString());
|
||||
return Utils::Fs::fromNativePath(value("Preferences/IPFilter/File").toString());
|
||||
}
|
||||
|
||||
void Preferences::setFilter(const QString &path)
|
||||
{
|
||||
setValue("Preferences/IPFilter/File", fsutils::fromNativePath(path));
|
||||
setValue("Preferences/IPFilter/File", Utils::Fs::fromNativePath(path));
|
||||
}
|
||||
|
||||
QStringList Preferences::bannedIPs() const
|
||||
@@ -1275,12 +1275,12 @@ void Preferences::setAutoRunEnabled(bool enabled)
|
||||
|
||||
QString Preferences::getAutoRunProgram() const
|
||||
{
|
||||
return fsutils::fromNativePath(value("AutoRun/program").toString());
|
||||
return Utils::Fs::fromNativePath(value("AutoRun/program").toString());
|
||||
}
|
||||
|
||||
void Preferences::setAutoRunProgram(const QString &program)
|
||||
{
|
||||
setValue("AutoRun/program", fsutils::fromNativePath(program));
|
||||
setValue("AutoRun/program", Utils::Fs::fromNativePath(program));
|
||||
}
|
||||
|
||||
bool Preferences::shutdownWhenDownloadsComplete() const
|
||||
@@ -1788,12 +1788,12 @@ bool Preferences::isMagnetLinkAssocSet()
|
||||
|
||||
// Check magnet link assoc
|
||||
QRegExp exe_reg("\"([^\"]+)\".*");
|
||||
QString shell_command = fsutils::toNativePath(settings.value("magnet/shell/open/command/Default", "").toString());
|
||||
QString shell_command = Utils::Fs::toNativePath(settings.value("magnet/shell/open/command/Default", "").toString());
|
||||
if (exe_reg.indexIn(shell_command) < 0)
|
||||
return false;
|
||||
QString assoc_exe = exe_reg.cap(1);
|
||||
qDebug("exe: %s", qPrintable(assoc_exe));
|
||||
if (assoc_exe.compare(fsutils::toNativePath(qApp->applicationFilePath()), Qt::CaseInsensitive) != 0)
|
||||
if (assoc_exe.compare(Utils::Fs::toNativePath(qApp->applicationFilePath()), Qt::CaseInsensitive) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -1829,9 +1829,9 @@ void Preferences::setMagnetLinkAssoc(bool set)
|
||||
settings.setValue("magnet/Default", "URL:Magnet link");
|
||||
settings.setValue("magnet/Content Type", "application/x-magnet");
|
||||
settings.setValue("magnet/URL Protocol", "");
|
||||
settings.setValue("magnet/DefaultIcon/Default", fsutils::toNativePath(icon_str));
|
||||
settings.setValue("magnet/DefaultIcon/Default", Utils::Fs::toNativePath(icon_str));
|
||||
settings.setValue("magnet/shell/Default", "open");
|
||||
settings.setValue("magnet/shell/open/command/Default", fsutils::toNativePath(command_str));
|
||||
settings.setValue("magnet/shell/open/command/Default", Utils::Fs::toNativePath(command_str));
|
||||
}
|
||||
else if (isMagnetLinkAssocSet()) {
|
||||
settings.remove("magnet");
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <QStringList>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include "misc.h"
|
||||
#include "fs_utils.h"
|
||||
#include "utils/misc.h"
|
||||
#include "utils/fs.h"
|
||||
#include "preferences.h"
|
||||
#include "filesystemwatcher.h"
|
||||
#include "bittorrent/session.h"
|
||||
@@ -122,7 +122,7 @@ QVariant ScanFoldersModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
const PathData *pathData = m_pathList.at(index.row());
|
||||
if ((index.column() == PathColumn) && (role == Qt::DisplayRole))
|
||||
return fsutils::toNativePath(pathData->path);
|
||||
return Utils::Fs::toNativePath(pathData->path);
|
||||
|
||||
if ((index.column() == DownloadAtTorrentColumn) && (role == Qt::CheckStateRole))
|
||||
return (pathData->downloadAtPath ? Qt::Checked : Qt::Unchecked);
|
||||
@@ -230,7 +230,7 @@ bool ScanFoldersModel::downloadInTorrentFolder(const QString &filePath) const
|
||||
int ScanFoldersModel::findPathData(const QString &path) const
|
||||
{
|
||||
for (int i = 0; i < m_pathList.count(); ++i)
|
||||
if (m_pathList.at(i)->path == fsutils::fromNativePath(path))
|
||||
if (m_pathList.at(i)->path == Utils::Fs::fromNativePath(path))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
@@ -285,7 +285,7 @@ void ScanFoldersModel::addTorrentsToSession(const QStringList &pathList)
|
||||
BitTorrent::TorrentInfo torrentInfo = BitTorrent::TorrentInfo::loadFromFile(file);
|
||||
if (torrentInfo.isValid()) {
|
||||
BitTorrent::Session::instance()->addTorrent(torrentInfo, params);
|
||||
fsutils::forceRemove(file);
|
||||
Utils::Fs::forceRemove(file);
|
||||
}
|
||||
else {
|
||||
qDebug("Ignoring incomplete torrent file: %s", qPrintable(file));
|
||||
|
||||
@@ -45,6 +45,7 @@ public:\
|
||||
|
||||
#define END_SCOPED_ENUM ; };
|
||||
|
||||
const qlonglong MAX_ETA = 8640000;
|
||||
|
||||
BEGIN_SCOPED_ENUM(MaxRatioAction)
|
||||
{
|
||||
@@ -60,4 +61,13 @@ BEGIN_SCOPED_ENUM(TorrentExportFolder)
|
||||
}
|
||||
END_SCOPED_ENUM
|
||||
|
||||
BEGIN_SCOPED_ENUM(ShutdownAction)
|
||||
{
|
||||
None,
|
||||
Shutdown,
|
||||
Suspend,
|
||||
Hibernate
|
||||
}
|
||||
END_SCOPED_ENUM
|
||||
|
||||
#endif // TYPES_H
|
||||
|
||||
492
src/core/utils/fs.cpp
Normal file
492
src/core/utils/fs.cpp
Normal file
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#elif defined(Q_OS_HAIKU)
|
||||
#include <kernel/fs_info.h>
|
||||
#else
|
||||
#include <sys/vfs.h>
|
||||
#endif
|
||||
#else
|
||||
#include <shlobj.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
#include <QDesktopServices>
|
||||
#else
|
||||
#include <QStandardPaths>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "misc.h"
|
||||
#include "fs.h"
|
||||
|
||||
/**
|
||||
* Converts a path to a string suitable for display.
|
||||
* This function makes sure the directory separator used is consistent
|
||||
* with the OS being run.
|
||||
*/
|
||||
QString Utils::Fs::toNativePath(const QString& path)
|
||||
{
|
||||
return QDir::toNativeSeparators(path);
|
||||
}
|
||||
|
||||
QString Utils::Fs::fromNativePath(const QString &path)
|
||||
{
|
||||
return QDir::fromNativeSeparators(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file extension part of a file name.
|
||||
*/
|
||||
QString Utils::Fs::fileExtension(const QString &filename)
|
||||
{
|
||||
QString ext = QString(filename).remove(".!qB");
|
||||
const int point_index = ext.lastIndexOf(".");
|
||||
return (point_index >= 0) ? ext.mid(point_index + 1) : QString();
|
||||
}
|
||||
|
||||
QString Utils::Fs::fileName(const QString& file_path)
|
||||
{
|
||||
QString path = fromNativePath(file_path);
|
||||
const int slash_index = path.lastIndexOf("/");
|
||||
if (slash_index == -1)
|
||||
return path;
|
||||
return path.mid(slash_index + 1);
|
||||
}
|
||||
|
||||
QString Utils::Fs::folderName(const QString& file_path)
|
||||
{
|
||||
QString path = fromNativePath(file_path);
|
||||
const int slash_index = path.lastIndexOf("/");
|
||||
if (slash_index == -1)
|
||||
return path;
|
||||
return path.left(slash_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an empty folder tree.
|
||||
*
|
||||
* This function will also remove .DS_Store files on Mac OS and
|
||||
* Thumbs.db on Windows.
|
||||
*/
|
||||
bool Utils::Fs::smartRemoveEmptyFolderTree(const QString& dir_path)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << dir_path;
|
||||
if (dir_path.isEmpty())
|
||||
return false;
|
||||
|
||||
QDir dir(dir_path);
|
||||
if (!dir.exists())
|
||||
return true;
|
||||
|
||||
// Remove Files created by the OS
|
||||
#if defined Q_OS_MAC
|
||||
forceRemove(dir_path + QLatin1String("/.DS_Store"));
|
||||
#elif defined Q_OS_WIN
|
||||
forceRemove(dir_path + QLatin1String("/Thumbs.db"));
|
||||
#endif
|
||||
|
||||
QFileInfoList sub_files = dir.entryInfoList();
|
||||
foreach (const QFileInfo& info, sub_files) {
|
||||
QString sub_name = info.fileName();
|
||||
if (sub_name == "." || sub_name == "..")
|
||||
continue;
|
||||
|
||||
QString sub_path = info.absoluteFilePath();
|
||||
qDebug() << Q_FUNC_INFO << "sub file: " << sub_path;
|
||||
if (info.isDir()) {
|
||||
if (!smartRemoveEmptyFolderTree(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove folder: " << sub_path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (info.isHidden()) {
|
||||
qDebug() << Q_FUNC_INFO << "Removing hidden file: " << sub_path;
|
||||
if (!forceRemove(sub_path)) {
|
||||
qWarning() << Q_FUNC_INFO << "Failed to remove " << sub_path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qWarning() << Q_FUNC_INFO << "Folder is not empty, aborting. Found: " << sub_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << Q_FUNC_INFO << "Calling rmdir on " << dir_path;
|
||||
return QDir().rmdir(dir_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the file with the given file_path.
|
||||
*
|
||||
* This function will try to fix the file permissions before removing it.
|
||||
*/
|
||||
bool Utils::Fs::forceRemove(const QString& file_path)
|
||||
{
|
||||
QFile f(file_path);
|
||||
if (!f.exists())
|
||||
return true;
|
||||
// Make sure we have read/write permissions
|
||||
f.setPermissions(f.permissions() | QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser);
|
||||
// Remove the file
|
||||
return f.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of a file.
|
||||
* If the file is a folder, it will compute its size based on its content.
|
||||
*
|
||||
* Returns -1 in case of error.
|
||||
*/
|
||||
qint64 Utils::Fs::computePathSize(const QString& path)
|
||||
{
|
||||
// Check if it is a file
|
||||
QFileInfo fi(path);
|
||||
if (!fi.exists()) return -1;
|
||||
if (fi.isFile()) return fi.size();
|
||||
// Compute folder size based on its content
|
||||
qint64 size = 0;
|
||||
foreach (const QFileInfo &subfi, QDir(path).entryInfoList(QDir::Dirs|QDir::Files)) {
|
||||
if (subfi.fileName().startsWith(".")) continue;
|
||||
if (subfi.isDir())
|
||||
size += computePathSize(subfi.absoluteFilePath());
|
||||
else
|
||||
size += subfi.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes deep comparison of two files to make sure they are identical.
|
||||
*/
|
||||
bool Utils::Fs::sameFiles(const QString& path1, const QString& path2)
|
||||
{
|
||||
QFile f1(path1), f2(path2);
|
||||
if (!f1.exists() || !f2.exists()) return false;
|
||||
if (f1.size() != f2.size()) return false;
|
||||
if (!f1.open(QIODevice::ReadOnly)) return false;
|
||||
if (!f2.open(QIODevice::ReadOnly)) {
|
||||
f1.close();
|
||||
return false;
|
||||
}
|
||||
bool same = true;
|
||||
while(!f1.atEnd() && !f2.atEnd()) {
|
||||
if (f1.read(1024) != f2.read(1024)) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
f1.close(); f2.close();
|
||||
return same;
|
||||
}
|
||||
|
||||
QString Utils::Fs::toValidFileSystemName(QString filename)
|
||||
{
|
||||
qDebug("toValidFSName: %s", qPrintable(filename));
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
filename.replace(regex, " ");
|
||||
qDebug("toValidFSName, result: %s", qPrintable(filename));
|
||||
return filename.trimmed();
|
||||
}
|
||||
|
||||
bool Utils::Fs::isValidFileSystemName(const QString& filename)
|
||||
{
|
||||
if (filename.isEmpty()) return false;
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
return !filename.contains(regex);
|
||||
}
|
||||
|
||||
qlonglong Utils::Fs::freeDiskSpaceOnPath(QString path)
|
||||
{
|
||||
if (path.isEmpty()) return -1;
|
||||
QDir dir_path(path);
|
||||
if (!dir_path.exists()) {
|
||||
QStringList parts = path.split("/");
|
||||
while (parts.size() > 1 && !QDir(parts.join("/")).exists()) {
|
||||
parts.removeLast();
|
||||
}
|
||||
dir_path = QDir(parts.join("/"));
|
||||
if (!dir_path.exists()) return -1;
|
||||
}
|
||||
Q_ASSERT(dir_path.exists());
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
unsigned long long available;
|
||||
#ifdef Q_OS_HAIKU
|
||||
const QString statfs_path = dir_path.path() + "/.";
|
||||
dev_t device = dev_for_path (qPrintable(statfs_path));
|
||||
if (device >= 0) {
|
||||
fs_info info;
|
||||
if (fs_stat_dev(device, &info) == B_OK) {
|
||||
available = ((unsigned long long)(info.free_blocks * info.block_size));
|
||||
return available;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
struct statfs stats;
|
||||
const QString statfs_path = dir_path.path() + "/.";
|
||||
const int ret = statfs(qPrintable(statfs_path), &stats);
|
||||
if (ret == 0) {
|
||||
available = ((unsigned long long)stats.f_bavail)
|
||||
* ((unsigned long long)stats.f_bsize);
|
||||
return available;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER,
|
||||
PULARGE_INTEGER);
|
||||
GetDiskFreeSpaceEx_t pGetDiskFreeSpaceEx =
|
||||
(GetDiskFreeSpaceEx_t)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "GetDiskFreeSpaceExW");
|
||||
if (pGetDiskFreeSpaceEx) {
|
||||
ULARGE_INTEGER bytesFree, bytesTotal;
|
||||
unsigned long long *ret;
|
||||
if (pGetDiskFreeSpaceEx((LPCTSTR)(toNativePath(dir_path.path())).utf16(), &bytesFree, &bytesTotal, NULL)) {
|
||||
ret = (unsigned long long*)&bytesFree;
|
||||
return *ret;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Utils::Fs::branchPath(const QString& file_path, QString* removed)
|
||||
{
|
||||
QString ret = fromNativePath(file_path);
|
||||
if (ret.endsWith("/"))
|
||||
ret.chop(1);
|
||||
const int slashIndex = ret.lastIndexOf("/");
|
||||
if (slashIndex >= 0) {
|
||||
if (removed)
|
||||
*removed = ret.mid(slashIndex + 1);
|
||||
ret = ret.left(slashIndex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Utils::Fs::sameFileNames(const QString &first, const QString &second)
|
||||
{
|
||||
#if defined(Q_OS_UNIX) || defined(Q_WS_QWS)
|
||||
return QString::compare(first, second, Qt::CaseSensitive) == 0;
|
||||
#else
|
||||
return QString::compare(first, second, Qt::CaseInsensitive) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Utils::Fs::expandPath(const QString &path)
|
||||
{
|
||||
QString ret = fromNativePath(path.trimmed());
|
||||
if (ret.isEmpty())
|
||||
return ret;
|
||||
|
||||
return QDir::cleanPath(ret);
|
||||
}
|
||||
|
||||
QString Utils::Fs::expandPathAbs(const QString& path)
|
||||
{
|
||||
QString ret = expandPath(path);
|
||||
|
||||
if (!QDir::isAbsolutePath(ret))
|
||||
ret = QDir(ret).absolutePath();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString Utils::Fs::QDesktopServicesDataLocation()
|
||||
{
|
||||
QString result;
|
||||
#ifdef Q_OS_WIN
|
||||
LPWSTR path=new WCHAR[256];
|
||||
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
||||
result = fromNativePath(QString::fromWCharArray(path));
|
||||
if (!QCoreApplication::applicationName().isEmpty())
|
||||
result += QLatin1String("/") + qApp->applicationName();
|
||||
#else
|
||||
#ifdef Q_OS_MAC
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QString path;
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
result += QLatin1Char('/') + qApp->applicationName();
|
||||
#else
|
||||
QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
|
||||
if (xdgDataHome.isEmpty())
|
||||
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
|
||||
xdgDataHome += QLatin1String("/data/")
|
||||
+ qApp->applicationName();
|
||||
result = xdgDataHome;
|
||||
#endif
|
||||
#endif
|
||||
if (!result.endsWith("/"))
|
||||
result += "/";
|
||||
return result;
|
||||
}
|
||||
|
||||
QString Utils::Fs::QDesktopServicesCacheLocation()
|
||||
{
|
||||
QString result;
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||
result = QDesktopServicesDataLocation() + QLatin1String("cache");
|
||||
#else
|
||||
#ifdef Q_OS_MAC
|
||||
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
|
||||
FSRef ref;
|
||||
OSErr err = FSFindFolder(kUserDomain, kCachedDataFolderType, false, &ref);
|
||||
if (err)
|
||||
return QString();
|
||||
QByteArray ba(2048, 0);
|
||||
if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr)
|
||||
result = QString::fromUtf8(ba).normalized(QString::NormalizationForm_C);
|
||||
result += QLatin1Char('/') + qApp->applicationName();
|
||||
#else
|
||||
QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
|
||||
if (xdgCacheHome.isEmpty())
|
||||
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
|
||||
xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
|
||||
result = xdgCacheHome;
|
||||
#endif
|
||||
#endif
|
||||
if (!result.endsWith("/"))
|
||||
result += "/";
|
||||
return result;
|
||||
}
|
||||
|
||||
QString Utils::Fs::QDesktopServicesDownloadLocation()
|
||||
{
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
|
||||
// as long as it stays WinXP like we do the same on OS/2
|
||||
// TODO: Use IKnownFolderManager to get path of FOLDERID_Downloads
|
||||
// instead of hardcoding "Downloads"
|
||||
// Unfortunately, this would break compatibility with WinXP
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
return QDir(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)).absoluteFilePath(
|
||||
QCoreApplication::translate("fsutils", "Downloads"));
|
||||
#else
|
||||
return QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).absoluteFilePath(
|
||||
QCoreApplication::translate("fsutils", "Downloads"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
||||
QString save_path;
|
||||
// Default save path on Linux
|
||||
QString config_path = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME").constData());
|
||||
if (config_path.isEmpty())
|
||||
config_path = QDir::home().absoluteFilePath(".config");
|
||||
|
||||
QString user_dirs_file = config_path + "/user-dirs.dirs";
|
||||
if (QFile::exists(user_dirs_file)) {
|
||||
QSettings settings(user_dirs_file, QSettings::IniFormat);
|
||||
// We need to force UTF-8 encoding here since this is not
|
||||
// the default for Ini files.
|
||||
settings.setIniCodec("UTF-8");
|
||||
QString xdg_download_dir = settings.value("XDG_DOWNLOAD_DIR").toString();
|
||||
if (!xdg_download_dir.isEmpty()) {
|
||||
// Resolve $HOME environment variables
|
||||
xdg_download_dir.replace("$HOME", QDir::homePath());
|
||||
save_path = xdg_download_dir;
|
||||
qDebug() << Q_FUNC_INFO << "SUCCESS: Using XDG path for downloads: " << save_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
if (!save_path.isEmpty() && !QFile::exists(save_path)) {
|
||||
QDir().mkpath(save_path);
|
||||
}
|
||||
|
||||
if (save_path.isEmpty() || !QFile::exists(save_path)) {
|
||||
save_path = QDir::home().absoluteFilePath(QCoreApplication::translate("fsutils", "Downloads"));
|
||||
qDebug() << Q_FUNC_INFO << "using" << save_path << "as fallback since the XDG detection did not work";
|
||||
}
|
||||
|
||||
return save_path;
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// TODO: How to support this on Mac OS X?
|
||||
#endif
|
||||
|
||||
// Fallback
|
||||
return QDir::home().absoluteFilePath(QCoreApplication::translate("fsutils", "Downloads"));
|
||||
}
|
||||
|
||||
QString Utils::Fs::searchEngineLocation()
|
||||
{
|
||||
QString folder = "nova";
|
||||
if (Utils::Misc::pythonVersion() >= 3)
|
||||
folder = "nova3";
|
||||
const QString location = expandPathAbs(QDesktopServicesDataLocation() + folder);
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
|
||||
QString Utils::Fs::cacheLocation()
|
||||
{
|
||||
QString location = expandPathAbs(QDesktopServicesCacheLocation());
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2012 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -28,43 +28,44 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef FS_UTILS_H
|
||||
#define FS_UTILS_H
|
||||
|
||||
#include <QString>
|
||||
#ifndef UTILS_FS_H
|
||||
#define UTILS_FS_H
|
||||
|
||||
/**
|
||||
* Utility functions related to file system.
|
||||
*/
|
||||
namespace fsutils
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
namespace Fs
|
||||
{
|
||||
QString toNativePath(const QString& path);
|
||||
QString fromNativePath(const QString& path);
|
||||
QString fileExtension(const QString& filename);
|
||||
QString fileName(const QString& file_path);
|
||||
QString folderName(const QString& file_path);
|
||||
qint64 computePathSize(const QString& path);
|
||||
bool sameFiles(const QString& path1, const QString& path2);
|
||||
QString toValidFileSystemName(QString filename);
|
||||
bool isValidFileSystemName(const QString& filename);
|
||||
qlonglong freeDiskSpaceOnPath(QString path);
|
||||
QString branchPath(const QString& file_path, QString* removed = 0);
|
||||
bool sameFileNames(const QString& first, const QString& second);
|
||||
QString expandPath(const QString& path);
|
||||
QString expandPathAbs(const QString& path);
|
||||
bool smartRemoveEmptyFolderTree(const QString& dir_path);
|
||||
bool forceRemove(const QString& file_path);
|
||||
|
||||
QString toNativePath(const QString& path);
|
||||
QString fromNativePath(const QString& path);
|
||||
QString fileExtension(const QString& filename);
|
||||
QString fileName(const QString& file_path);
|
||||
QString folderName(const QString& file_path);
|
||||
qint64 computePathSize(const QString& path);
|
||||
bool sameFiles(const QString& path1, const QString& path2);
|
||||
QString toValidFileSystemName(QString filename);
|
||||
bool isValidFileSystemName(const QString& filename);
|
||||
long long freeDiskSpaceOnPath(QString path);
|
||||
QString branchPath(const QString& file_path, QString* removed = 0);
|
||||
bool sameFileNames(const QString& first, const QString& second);
|
||||
QString expandPath(const QString& path);
|
||||
QString expandPathAbs(const QString& path);
|
||||
bool smartRemoveEmptyFolderTree(const QString& dir_path);
|
||||
bool forceRemove(const QString& file_path);
|
||||
|
||||
/* Ported from Qt4 to drop dependency on QtGui */
|
||||
QString QDesktopServicesDataLocation();
|
||||
QString QDesktopServicesCacheLocation();
|
||||
QString QDesktopServicesDownloadLocation();
|
||||
/* End of Qt4 code */
|
||||
QString searchEngineLocation();
|
||||
QString cacheLocation();
|
||||
|
||||
/* Ported from Qt4 to drop dependency on QtGui */
|
||||
QString QDesktopServicesDataLocation();
|
||||
QString QDesktopServicesCacheLocation();
|
||||
QString QDesktopServicesDownloadLocation();
|
||||
/* End of Qt4 code */
|
||||
QString searchEngineLocation();
|
||||
QString cacheLocation();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // FS_UTILS_H
|
||||
|
||||
#endif // UTILS_FS_H
|
||||
@@ -28,8 +28,6 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QUrl>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
@@ -38,7 +36,6 @@
|
||||
#include <QDebug>
|
||||
#include <QProcess>
|
||||
#include <QSettings>
|
||||
#include <QLocale>
|
||||
#include <QThread>
|
||||
|
||||
#ifdef DISABLE_GUI
|
||||
@@ -69,6 +66,7 @@ const int UNLEN = 256;
|
||||
#endif
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
#include "core/utils/string.h"
|
||||
#include "misc.h"
|
||||
|
||||
static struct { const char *source; const char *comment; } units[] = {
|
||||
@@ -80,16 +78,16 @@ static struct { const char *source; const char *comment; } units[] = {
|
||||
};
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
void misc::shutdownComputer(ShutDownAction action)
|
||||
void Utils::Misc::shutdownComputer(ShutdownAction action)
|
||||
{
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB)
|
||||
// Use dbus to power off / suspend the system
|
||||
if (action != SHUTDOWN_COMPUTER) {
|
||||
if (action != ShutdownAction::Shutdown) {
|
||||
// Some recent systems use systemd's logind
|
||||
QDBusInterface login1Iface("org.freedesktop.login1", "/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager", QDBusConnection::systemBus());
|
||||
if (login1Iface.isValid()) {
|
||||
if (action == SUSPEND_COMPUTER)
|
||||
if (action == ShutdownAction::Suspend)
|
||||
login1Iface.call("Suspend", false);
|
||||
else
|
||||
login1Iface.call("Hibernate", false);
|
||||
@@ -99,7 +97,7 @@ void misc::shutdownComputer(ShutDownAction action)
|
||||
QDBusInterface upowerIface("org.freedesktop.UPower", "/org/freedesktop/UPower",
|
||||
"org.freedesktop.UPower", QDBusConnection::systemBus());
|
||||
if (upowerIface.isValid()) {
|
||||
if (action == SUSPEND_COMPUTER)
|
||||
if (action == ShutdownAction::Suspend)
|
||||
upowerIface.call("Suspend");
|
||||
else
|
||||
upowerIface.call("Hibernate");
|
||||
@@ -109,7 +107,7 @@ void misc::shutdownComputer(ShutDownAction action)
|
||||
QDBusInterface halIface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer",
|
||||
"org.freedesktop.Hal.Device.SystemPowerManagement",
|
||||
QDBusConnection::systemBus());
|
||||
if (action == SUSPEND_COMPUTER)
|
||||
if (action == ShutdownAction::Suspend)
|
||||
halIface.call("Suspend", 5);
|
||||
else
|
||||
halIface.call("Hibernate");
|
||||
@@ -138,7 +136,7 @@ void misc::shutdownComputer(ShutDownAction action)
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
AEEventID EventToSend;
|
||||
if (action != SHUTDOWN_COMPUTER)
|
||||
if (action != ShutdownAction::Shutdown)
|
||||
EventToSend = kAESleep;
|
||||
else
|
||||
EventToSend = kAEShutDown;
|
||||
@@ -193,9 +191,9 @@ void misc::shutdownComputer(ShutDownAction action)
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
if (action == SUSPEND_COMPUTER)
|
||||
if (action == ShutdownAction::Suspend)
|
||||
SetSuspendState(false, false, false);
|
||||
else if (action == HIBERNATE_COMPUTER)
|
||||
else if (action == ShutdownAction::Hibernate)
|
||||
SetSuspendState(true, false, false);
|
||||
else
|
||||
InitiateSystemShutdownA(0, QCoreApplication::translate("misc", "qBittorrent will shutdown the computer now because all downloads are complete.").toLocal8Bit().data(), 10, true, false);
|
||||
@@ -210,7 +208,7 @@ void misc::shutdownComputer(ShutDownAction action)
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
// Get screen center
|
||||
QPoint misc::screenCenter(QWidget *win)
|
||||
QPoint Utils::Misc::screenCenter(QWidget *win)
|
||||
{
|
||||
int scrn = 0;
|
||||
const QWidget *w = win->window();
|
||||
@@ -231,7 +229,7 @@ QPoint misc::screenCenter(QWidget *win)
|
||||
* Detects the version of python by calling
|
||||
* "python --version" and parsing the output.
|
||||
*/
|
||||
int misc::pythonVersion()
|
||||
int Utils::Misc::pythonVersion()
|
||||
{
|
||||
static int version = -1;
|
||||
if (version < 0) {
|
||||
@@ -257,7 +255,7 @@ int misc::pythonVersion()
|
||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||
// value must be given in bytes
|
||||
// to send numbers instead of strings with suffixes
|
||||
QString misc::friendlyUnit(qreal val, bool is_speed)
|
||||
QString Utils::Misc::friendlyUnit(qreal val, bool is_speed)
|
||||
{
|
||||
if (val < 0)
|
||||
return QCoreApplication::translate("misc", "Unknown", "Unknown (size)");
|
||||
@@ -268,13 +266,13 @@ QString misc::friendlyUnit(qreal val, bool is_speed)
|
||||
if (i == 0)
|
||||
ret = QString::number((long)val) + " " + QCoreApplication::translate("misc", units[0].source, units[0].comment);
|
||||
else
|
||||
ret = accurateDoubleToString(val, 1) + " " + QCoreApplication::translate("misc", units[i].source, units[i].comment);
|
||||
ret = Utils::String::fromDouble(val, 1) + " " + QCoreApplication::translate("misc", units[i].source, units[i].comment);
|
||||
if (is_speed)
|
||||
ret += QCoreApplication::translate("misc", "/s", "per second");
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool misc::isPreviewable(const QString& extension)
|
||||
bool Utils::Misc::isPreviewable(const QString& extension)
|
||||
{
|
||||
static QSet<QString> multimedia_extensions;
|
||||
if (multimedia_extensions.empty()) {
|
||||
@@ -327,7 +325,7 @@ bool misc::isPreviewable(const QString& extension)
|
||||
return multimedia_extensions.contains(extension.toUpper());
|
||||
}
|
||||
|
||||
QString misc::bcLinkToMagnet(QString bc_link)
|
||||
QString Utils::Misc::bcLinkToMagnet(QString bc_link)
|
||||
{
|
||||
QByteArray raw_bc = bc_link.toUtf8();
|
||||
raw_bc = raw_bc.mid(8); // skip bc://bt/
|
||||
@@ -344,7 +342,7 @@ QString misc::bcLinkToMagnet(QString bc_link)
|
||||
|
||||
// Take a number of seconds and return an user-friendly
|
||||
// time duration like "1d 2h 10m".
|
||||
QString misc::userFriendlyDuration(qlonglong seconds)
|
||||
QString Utils::Misc::userFriendlyDuration(qlonglong seconds)
|
||||
{
|
||||
if (seconds < 0 || seconds >= MAX_ETA)
|
||||
return QString::fromUtf8("∞");
|
||||
@@ -366,7 +364,7 @@ QString misc::userFriendlyDuration(qlonglong seconds)
|
||||
return QString::fromUtf8("∞");
|
||||
}
|
||||
|
||||
QString misc::getUserIDString()
|
||||
QString Utils::Misc::getUserIDString()
|
||||
{
|
||||
QString uid = "0";
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -380,7 +378,7 @@ QString misc::getUserIDString()
|
||||
return uid;
|
||||
}
|
||||
|
||||
QStringList misc::toStringList(const QList<bool> &l)
|
||||
QStringList Utils::Misc::toStringList(const QList<bool> &l)
|
||||
{
|
||||
QStringList ret;
|
||||
foreach (const bool &b, l)
|
||||
@@ -388,7 +386,7 @@ QStringList misc::toStringList(const QList<bool> &l)
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<int> misc::intListfromStringList(const QStringList &l)
|
||||
QList<int> Utils::Misc::intListfromStringList(const QStringList &l)
|
||||
{
|
||||
QList<int> ret;
|
||||
foreach (const QString &s, l)
|
||||
@@ -396,7 +394,7 @@ QList<int> misc::intListfromStringList(const QStringList &l)
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<bool> misc::boolListfromStringList(const QStringList &l)
|
||||
QList<bool> Utils::Misc::boolListfromStringList(const QStringList &l)
|
||||
{
|
||||
QList<bool> ret;
|
||||
foreach (const QString &s, l)
|
||||
@@ -404,14 +402,14 @@ QList<bool> misc::boolListfromStringList(const QStringList &l)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool misc::isUrl(const QString &s)
|
||||
bool Utils::Misc::isUrl(const QString &s)
|
||||
{
|
||||
const QString scheme = QUrl(s).scheme();
|
||||
QRegExp is_url("http[s]?|ftp", Qt::CaseInsensitive);
|
||||
return is_url.exactMatch(scheme);
|
||||
}
|
||||
|
||||
QString misc::parseHtmlLinks(const QString &raw_text)
|
||||
QString Utils::Misc::parseHtmlLinks(const QString &raw_text)
|
||||
{
|
||||
QString result = raw_text;
|
||||
static QRegExp reURL(
|
||||
@@ -472,107 +470,20 @@ QString misc::parseHtmlLinks(const QString &raw_text)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
bool misc::naturalSort(QString left, QString right, bool &result) // uses lessThan comparison
|
||||
{ // Return value indicates if functions was successful
|
||||
// result argument will contain actual comparison result if function was successful
|
||||
int posL = 0;
|
||||
int posR = 0;
|
||||
do {
|
||||
for (;; ) {
|
||||
if (posL == left.size() || posR == right.size())
|
||||
return false; // No data
|
||||
|
||||
QChar leftChar = left.at(posL);
|
||||
QChar rightChar = right.at(posR);
|
||||
bool leftCharIsDigit = leftChar.isDigit();
|
||||
bool rightCharIsDigit = rightChar.isDigit();
|
||||
if (leftCharIsDigit != rightCharIsDigit)
|
||||
return false; // Digit positions mismatch
|
||||
|
||||
if (leftCharIsDigit)
|
||||
break; // Both are digit, break this loop and compare numbers
|
||||
|
||||
if (leftChar != rightChar)
|
||||
return false; // Strings' subsets before digit do not match
|
||||
|
||||
++posL;
|
||||
++posR;
|
||||
}
|
||||
|
||||
QString temp;
|
||||
while (posL < left.size()) {
|
||||
if (left.at(posL).isDigit())
|
||||
temp += left.at(posL);
|
||||
else
|
||||
break;
|
||||
posL++;
|
||||
}
|
||||
int numL = temp.toInt();
|
||||
temp.clear();
|
||||
|
||||
while (posR < right.size()) {
|
||||
if (right.at(posR).isDigit())
|
||||
temp += right.at(posR);
|
||||
else
|
||||
break;
|
||||
posR++;
|
||||
}
|
||||
int numR = temp.toInt();
|
||||
|
||||
if (numL != numR) {
|
||||
result = (numL < numR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Strings + digits do match and we haven't hit string end
|
||||
// Do another round
|
||||
|
||||
} while (true);
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// to send numbers instead of strings with suffixes
|
||||
QString misc::accurateDoubleToString(const double &n, const int &precision)
|
||||
namespace
|
||||
{
|
||||
/* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9
|
||||
** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 The problem manifests when
|
||||
** the number has more digits after the decimal than we want AND the digit after
|
||||
** our 'wanted' is >= 5. In this case our last digit gets rounded up. So for each
|
||||
** precision we add an extra 0 behind 1 in the below algorithm. */
|
||||
|
||||
double prec = std::pow(10.0, precision);
|
||||
return QLocale::system().toString(std::floor(n * prec) / prec, 'f', precision);
|
||||
}
|
||||
|
||||
// Implements constant-time comparison to protect against timing attacks
|
||||
// Taken from https://crackstation.net/hashing-security.htm
|
||||
bool misc::slowEquals(const QByteArray &a, const QByteArray &b)
|
||||
{
|
||||
int lengthA = a.length();
|
||||
int lengthB = b.length();
|
||||
|
||||
int diff = lengthA ^ lengthB;
|
||||
for(int i = 0; i < lengthA && i < lengthB; i++)
|
||||
diff |= a[i] ^ b[i];
|
||||
|
||||
return (diff == 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Trick to get a portable sleep() function
|
||||
class SleeperThread: public QThread {
|
||||
public:
|
||||
static void msleep(unsigned long msecs)
|
||||
// Trick to get a portable sleep() function
|
||||
class SleeperThread : public QThread
|
||||
{
|
||||
QThread::msleep(msecs);
|
||||
}
|
||||
};
|
||||
public:
|
||||
static void msleep(unsigned long msecs)
|
||||
{
|
||||
QThread::msleep(msecs);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void misc::msleep(unsigned long msecs)
|
||||
void Utils::Misc::msleep(unsigned long msecs)
|
||||
{
|
||||
SleeperThread::msleep(msecs);
|
||||
}
|
||||
@@ -28,8 +28,8 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
#ifndef UTILS_MISC_H
|
||||
#define UTILS_MISC_H
|
||||
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
@@ -39,57 +39,43 @@
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
|
||||
namespace BitTorrent { class TorrentHandle; }
|
||||
|
||||
const qlonglong MAX_ETA = 8640000;
|
||||
enum ShutDownAction { NO_SHUTDOWN, SHUTDOWN_COMPUTER, SUSPEND_COMPUTER, HIBERNATE_COMPUTER };
|
||||
#include "core/types.h"
|
||||
|
||||
/* Miscellaneaous functions that can be useful */
|
||||
namespace misc
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
namespace Misc
|
||||
{
|
||||
QString parseHtmlLinks(const QString &raw_text);
|
||||
bool isUrl(const QString &s);
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
void shutdownComputer(ShutDownAction action = SHUTDOWN_COMPUTER);
|
||||
void shutdownComputer(ShutdownAction action);
|
||||
// Get screen center
|
||||
QPoint screenCenter(QWidget *win);
|
||||
#endif
|
||||
int pythonVersion();
|
||||
// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB)
|
||||
// use Binary prefix standards from IEC 60027-2
|
||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||
// value must be given in bytes
|
||||
QString friendlyUnit(qreal val, bool is_speed = false);
|
||||
bool isPreviewable(const QString& extension);
|
||||
|
||||
QString parseHtmlLinks(const QString &raw_text);
|
||||
QString bcLinkToMagnet(QString bc_link);
|
||||
// Take a number of seconds and return an user-friendly
|
||||
// time duration like "1d 2h 10m".
|
||||
QString userFriendlyDuration(qlonglong seconds);
|
||||
QString getUserIDString();
|
||||
|
||||
bool isUrl(const QString &s);
|
||||
// Convert functions
|
||||
QStringList toStringList(const QList<bool> &l);
|
||||
QList<int> intListfromStringList(const QStringList &l);
|
||||
QList<bool> boolListfromStringList(const QStringList &l);
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
// Get screen center
|
||||
QPoint screenCenter(QWidget *win);
|
||||
#endif
|
||||
int pythonVersion();
|
||||
// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB)
|
||||
// use Binary prefix standards from IEC 60027-2
|
||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||
// value must be given in bytes
|
||||
QString friendlyUnit(qreal val, bool is_speed = false);
|
||||
bool isPreviewable(const QString& extension);
|
||||
|
||||
QString bcLinkToMagnet(QString bc_link);
|
||||
// Take a number of seconds and return an user-friendly
|
||||
// time duration like "1d 2h 10m".
|
||||
QString userFriendlyDuration(qlonglong seconds);
|
||||
QString getUserIDString();
|
||||
|
||||
// Convert functions
|
||||
QStringList toStringList(const QList<bool> &l);
|
||||
QList<int> intListfromStringList(const QStringList &l);
|
||||
QList<bool> boolListfromStringList(const QStringList &l);
|
||||
|
||||
QString accurateDoubleToString(const double &n, const int &precision);
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
bool naturalSort(QString left, QString right, bool& result);
|
||||
#endif
|
||||
|
||||
// Implements constant-time comparison to protect against timing attacks
|
||||
// Taken from https://crackstation.net/hashing-security.htm
|
||||
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
||||
void msleep(unsigned long msecs);
|
||||
void msleep(unsigned long msecs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -29,15 +29,106 @@
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QLocale>
|
||||
#include <cmath>
|
||||
#include "string.h"
|
||||
|
||||
QString String::fromStdString(const std::string &str)
|
||||
QString Utils::String::fromStdString(const std::string &str)
|
||||
{
|
||||
return QString::fromUtf8(str.c_str());
|
||||
}
|
||||
|
||||
std::string String::toStdString(const QString &str)
|
||||
std::string Utils::String::toStdString(const QString &str)
|
||||
{
|
||||
QByteArray utf8 = str.toUtf8();
|
||||
return std::string(utf8.constData(), utf8.length());
|
||||
}
|
||||
|
||||
// uses lessThan comparison
|
||||
bool Utils::String::naturalSort(QString left, QString right, bool &result)
|
||||
{
|
||||
// Return value indicates if functions was successful
|
||||
// result argument will contain actual comparison result if function was successful
|
||||
int posL = 0;
|
||||
int posR = 0;
|
||||
do {
|
||||
forever {
|
||||
if (posL == left.size() || posR == right.size())
|
||||
return false; // No data
|
||||
|
||||
QChar leftChar = left.at(posL);
|
||||
QChar rightChar = right.at(posR);
|
||||
bool leftCharIsDigit = leftChar.isDigit();
|
||||
bool rightCharIsDigit = rightChar.isDigit();
|
||||
if (leftCharIsDigit != rightCharIsDigit)
|
||||
return false; // Digit positions mismatch
|
||||
|
||||
if (leftCharIsDigit)
|
||||
break; // Both are digit, break this loop and compare numbers
|
||||
|
||||
if (leftChar != rightChar)
|
||||
return false; // Strings' subsets before digit do not match
|
||||
|
||||
++posL;
|
||||
++posR;
|
||||
}
|
||||
|
||||
QString temp;
|
||||
while (posL < left.size()) {
|
||||
if (left.at(posL).isDigit())
|
||||
temp += left.at(posL);
|
||||
else
|
||||
break;
|
||||
posL++;
|
||||
}
|
||||
int numL = temp.toInt();
|
||||
temp.clear();
|
||||
|
||||
while (posR < right.size()) {
|
||||
if (right.at(posR).isDigit())
|
||||
temp += right.at(posR);
|
||||
else
|
||||
break;
|
||||
posR++;
|
||||
}
|
||||
int numR = temp.toInt();
|
||||
|
||||
if (numL != numR) {
|
||||
result = (numL < numR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Strings + digits do match and we haven't hit string end
|
||||
// Do another round
|
||||
|
||||
} while (true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// to send numbers instead of strings with suffixes
|
||||
QString Utils::String::fromDouble(double n, int precision)
|
||||
{
|
||||
/* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9
|
||||
** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 The problem manifests when
|
||||
** the number has more digits after the decimal than we want AND the digit after
|
||||
** our 'wanted' is >= 5. In this case our last digit gets rounded up. So for each
|
||||
** precision we add an extra 0 behind 1 in the below algorithm. */
|
||||
|
||||
double prec = std::pow(10.0, precision);
|
||||
return QLocale::system().toString(std::floor(n * prec) / prec, 'f', precision);
|
||||
}
|
||||
|
||||
// Implements constant-time comparison to protect against timing attacks
|
||||
// Taken from https://crackstation.net/hashing-security.htm
|
||||
bool Utils::String::slowEquals(const QByteArray &a, const QByteArray &b)
|
||||
{
|
||||
int lengthA = a.length();
|
||||
int lengthB = b.length();
|
||||
|
||||
int diff = lengthA ^ lengthB;
|
||||
for (int i = 0; (i < lengthA) && (i < lengthB); i++)
|
||||
diff |= a[i] ^ b[i];
|
||||
|
||||
return (diff == 0);
|
||||
}
|
||||
|
||||
@@ -33,11 +33,21 @@
|
||||
#include <string>
|
||||
|
||||
class QString;
|
||||
class QByteArray;
|
||||
|
||||
namespace String
|
||||
namespace Utils
|
||||
{
|
||||
QString fromStdString(const std::string &str);
|
||||
std::string toStdString(const QString &str);
|
||||
namespace String
|
||||
{
|
||||
QString fromStdString(const std::string &str);
|
||||
std::string toStdString(const QString &str);
|
||||
bool naturalSort(QString left, QString right, bool &result);
|
||||
QString fromDouble(double n, int precision);
|
||||
|
||||
// Implements constant-time comparison to protect against timing attacks
|
||||
// Taken from https://crackstation.net/hashing-security.htm
|
||||
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTILS_STRING_H
|
||||
|
||||
Reference in New Issue
Block a user