diff --git a/src/misc.cpp b/src/misc.cpp index 1718d9580..f3b1952ca 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -82,183 +82,185 @@ const int UNLEN = 256; using namespace libtorrent; static struct { const char *source; const char *comment; } units[] = { - QT_TRANSLATE_NOOP3("misc", "B", "bytes"), - QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"), - QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"), - QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"), - QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)") + QT_TRANSLATE_NOOP3("misc", "B", "bytes"), + QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"), + QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"), + QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"), + QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)") }; -QString misc::toQString(const std::string &str) { - return QString::fromLocal8Bit(str.c_str()); +QString misc::toQString(const std::string &str) +{ + return QString::fromLocal8Bit(str.c_str()); } -QString misc::toQString(const char* str) { - return QString::fromLocal8Bit(str); +QString misc::toQString(const char* str) +{ + return QString::fromLocal8Bit(str); } -QString misc::toQStringU(const std::string &str) { - return QString::fromUtf8(str.c_str()); +QString misc::toQStringU(const std::string &str) +{ + return QString::fromUtf8(str.c_str()); } -QString misc::toQStringU(const char* str) { - return QString::fromUtf8(str); +QString misc::toQStringU(const char* str) +{ + return QString::fromUtf8(str); } -QString misc::toQString(const libtorrent::sha1_hash &hash) { - char out[41]; - libtorrent::to_hex((char const*)&hash[0], libtorrent::sha1_hash::size, out); - return QString(out); +QString misc::toQString(const libtorrent::sha1_hash &hash) +{ + char out[41]; + libtorrent::to_hex((char const*)&hash[0], libtorrent::sha1_hash::size, out); + return QString(out); } #ifndef DISABLE_GUI -void misc::shutdownComputer(shutDownAction action) { +void 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) { - // 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) - login1Iface.call("Suspend", false); - else - login1Iface.call("Hibernate", false); - return; + // Use dbus to power off / suspend the system + if (action != SHUTDOWN_COMPUTER) { + // 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) + login1Iface.call("Suspend", false); + else + login1Iface.call("Hibernate", false); + return; + } + // Else, other recent systems use UPower + QDBusInterface upowerIface("org.freedesktop.UPower", "/org/freedesktop/UPower", + "org.freedesktop.UPower", QDBusConnection::systemBus()); + if (upowerIface.isValid()) { + if (action == SUSPEND_COMPUTER) + upowerIface.call("Suspend"); + else + upowerIface.call("Hibernate"); + return; + } + // HAL (older systems) + QDBusInterface halIface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", + "org.freedesktop.Hal.Device.SystemPowerManagement", + QDBusConnection::systemBus()); + if (action == SUSPEND_COMPUTER) + halIface.call("Suspend", 5); + else + halIface.call("Hibernate"); } - // Else, other recent systems use UPower - QDBusInterface upowerIface("org.freedesktop.UPower", "/org/freedesktop/UPower", - "org.freedesktop.UPower", QDBusConnection::systemBus()); - if (upowerIface.isValid()) { - if (action == SUSPEND_COMPUTER) - upowerIface.call("Suspend"); - else - upowerIface.call("Hibernate"); - return; + else { + // Some recent systems use systemd's logind + QDBusInterface login1Iface("org.freedesktop.login1", "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); + if (login1Iface.isValid()) { + login1Iface.call("PowerOff", false); + return; + } + // Else, other recent systems use ConsoleKit + QDBusInterface consolekitIface("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", QDBusConnection::systemBus()); + if (consolekitIface.isValid()) { + consolekitIface.call("Stop"); + return; + } + // HAL (older systems) + QDBusInterface halIface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", + "org.freedesktop.Hal.Device.SystemPowerManagement", + QDBusConnection::systemBus()); + halIface.call("Shutdown"); } - // HAL (older systems) - QDBusInterface halIface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", - "org.freedesktop.Hal.Device.SystemPowerManagement", - QDBusConnection::systemBus()); - if (action == SUSPEND_COMPUTER) - halIface.call("Suspend", 5); - else - halIface.call("Hibernate"); - } else { - // Some recent systems use systemd's logind - QDBusInterface login1Iface("org.freedesktop.login1", "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); - if (login1Iface.isValid()) { - login1Iface.call("PowerOff", false); - return; - } - // Else, other recent systems use ConsoleKit - QDBusInterface consolekitIface("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", - "org.freedesktop.ConsoleKit.Manager", QDBusConnection::systemBus()); - if (consolekitIface.isValid()) { - consolekitIface.call("Stop"); - return; - } - // HAL (older systems) - QDBusInterface halIface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", - "org.freedesktop.Hal.Device.SystemPowerManagement", - QDBusConnection::systemBus()); - halIface.call("Shutdown"); - } #endif #ifdef Q_OS_MAC - AEEventID EventToSend; - if (action != SHUTDOWN_COMPUTER) - EventToSend = kAESleep; - else - EventToSend = kAEShutDown; - AEAddressDesc targetDesc; - static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess }; - AppleEvent eventReply = {typeNull, NULL}; - AppleEvent appleEventToSend = {typeNull, NULL}; + AEEventID EventToSend; + if (action != SHUTDOWN_COMPUTER) + EventToSend = kAESleep; + else + EventToSend = kAEShutDown; + AEAddressDesc targetDesc; + static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess }; + AppleEvent eventReply = {typeNull, NULL}; + AppleEvent appleEventToSend = {typeNull, NULL}; - OSStatus error = noErr; + OSStatus error = noErr; - error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess, - sizeof(kPSNOfSystemProcess), &targetDesc); + error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess, + sizeof(kPSNOfSystemProcess), &targetDesc); - if (error != noErr) - { - return; - } + if (error != noErr) + return; - error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc, - kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend); + error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc, + kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend); - AEDisposeDesc(&targetDesc); - if (error != noErr) - { - return; - } + AEDisposeDesc(&targetDesc); + if (error != noErr) + return; - error = AESend(&appleEventToSend, &eventReply, kAENoReply, - kAENormalPriority, kAEDefaultTimeout, NULL, NULL); + error = AESend(&appleEventToSend, &eventReply, kAENoReply, + kAENormalPriority, kAEDefaultTimeout, NULL, NULL); - AEDisposeDesc(&appleEventToSend); - if (error != noErr) - { - return; - } + AEDisposeDesc(&appleEventToSend); + if (error != noErr) + return; - AEDisposeDesc(&eventReply); + AEDisposeDesc(&eventReply); #endif #ifdef Q_OS_WIN - HANDLE hToken; // handle to process token - TOKEN_PRIVILEGES tkp; // pointer to token structure - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - return; - // Get the LUID for shutdown privilege. - LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, - &tkp.Privileges[0].Luid); + HANDLE hToken; // handle to process token + TOKEN_PRIVILEGES tkp; // pointer to token structure + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + return; + // Get the LUID for shutdown privilege. + LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, + &tkp.Privileges[0].Luid); - tkp.PrivilegeCount = 1; // one privilege to set - tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tkp.PrivilegeCount = 1; // one privilege to set + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - // Get shutdown privilege for this process. + // Get shutdown privilege for this process. - AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, - (PTOKEN_PRIVILEGES) NULL, 0); + AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, + (PTOKEN_PRIVILEGES) NULL, 0); - // Cannot test the return value of AdjustTokenPrivileges. + // Cannot test the return value of AdjustTokenPrivileges. - if (GetLastError() != ERROR_SUCCESS) - return; + if (GetLastError() != ERROR_SUCCESS) + return; - if (action == SUSPEND_COMPUTER) - SetSuspendState(false, false, false); - else if (action == HIBERNATE_COMPUTER) - 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); + if (action == SUSPEND_COMPUTER) + SetSuspendState(false, false, false); + else if (action == HIBERNATE_COMPUTER) + 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); - // Disable shutdown privilege. - tkp.Privileges[0].Attributes = 0; - AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, - (PTOKEN_PRIVILEGES) NULL, 0); + // Disable shutdown privilege. + tkp.Privileges[0].Attributes = 0; + AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, + (PTOKEN_PRIVILEGES) NULL, 0); #endif } #endif // DISABLE_GUI #ifndef DISABLE_GUI // Get screen center -QPoint misc::screenCenter(QWidget *win) { - int scrn = 0; - const QWidget *w = win->window(); +QPoint misc::screenCenter(QWidget *win) +{ + int scrn = 0; + const QWidget *w = win->window(); - if (w) - scrn = QApplication::desktop()->screenNumber(w); - else if (QApplication::desktop()->isVirtualDesktop()) - scrn = QApplication::desktop()->screenNumber(QCursor::pos()); - else - scrn = QApplication::desktop()->screenNumber(win); + if (w) + scrn = QApplication::desktop()->screenNumber(w); + else if (QApplication::desktop()->isVirtualDesktop()) + scrn = QApplication::desktop()->screenNumber(QCursor::pos()); + else + scrn = QApplication::desktop()->screenNumber(win); - QRect desk(QApplication::desktop()->availableGeometry(scrn)); - return QPoint((desk.width() - win->frameGeometry().width()) / 2, (desk.height() - win->frameGeometry().height()) / 2); + QRect desk(QApplication::desktop()->availableGeometry(scrn)); + return QPoint((desk.width() - win->frameGeometry().width()) / 2, (desk.height() - win->frameGeometry().height()) / 2); } #endif @@ -266,24 +268,25 @@ QPoint misc::screenCenter(QWidget *win) { * Detects the version of python by calling * "python --version" and parsing the output. */ -int misc::pythonVersion() { - static int version = -1; - if (version < 0) { - QProcess python_proc; - python_proc.start("python", QStringList() << "--version", QIODevice::ReadOnly); - if (!python_proc.waitForFinished()) return -1; - if (python_proc.exitCode() < 0) return -1; - QByteArray output = python_proc.readAllStandardOutput(); - if (output.isEmpty()) - output = python_proc.readAllStandardError(); - const QByteArray version_str = output.split(' ').last(); - qDebug() << "Python version is:" << version_str.trimmed(); - if (version_str.startsWith("3.")) - version = 3; - else - version = 2; - } - return version; +int misc::pythonVersion() +{ + static int version = -1; + if (version < 0) { + QProcess python_proc; + python_proc.start("python", QStringList() << "--version", QIODevice::ReadOnly); + if (!python_proc.waitForFinished()) return -1; + if (python_proc.exitCode() < 0) return -1; + QByteArray output = python_proc.readAllStandardOutput(); + if (output.isEmpty()) + output = python_proc.readAllStandardError(); + const QByteArray version_str = output.split(' ').last(); + qDebug() << "Python version is:" << version_str.trimmed(); + if (version_str.startsWith("3.")) + version = 3; + else + version = 2; + } + return version; } // return best userfriendly storage unit (B, KiB, MiB, GiB, TiB) @@ -291,369 +294,371 @@ 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) { - if (val < 0) - return QCoreApplication::translate("misc", "Unknown", "Unknown (size)"); - int i = 0; - while(val >= 1024. && i++<6) - val /= 1024.; - QString ret; - 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); - if (is_speed) - ret += QCoreApplication::translate("misc", "/s", "per second"); - return ret; +QString misc::friendlyUnit(qreal val, bool is_speed) +{ + if (val < 0) + return QCoreApplication::translate("misc", "Unknown", "Unknown (size)"); + int i = 0; + while(val >= 1024. && i++<6) + val /= 1024.; + QString ret; + 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); + if (is_speed) + ret += QCoreApplication::translate("misc", "/s", "per second"); + return ret; } -bool misc::isPreviewable(const QString& extension) { - static QSet multimedia_extensions; - if (multimedia_extensions.empty()) { - multimedia_extensions.insert("3GP"); - multimedia_extensions.insert("AAC"); - multimedia_extensions.insert("AC3"); - multimedia_extensions.insert("AIF"); - multimedia_extensions.insert("AIFC"); - multimedia_extensions.insert("AIFF"); - multimedia_extensions.insert("ASF"); - multimedia_extensions.insert("AU"); - multimedia_extensions.insert("AVI"); - multimedia_extensions.insert("FLAC"); - multimedia_extensions.insert("FLV"); - multimedia_extensions.insert("M3U"); - multimedia_extensions.insert("M4A"); - multimedia_extensions.insert("M4P"); - multimedia_extensions.insert("M4V"); - multimedia_extensions.insert("MID"); - multimedia_extensions.insert("MKV"); - multimedia_extensions.insert("MOV"); - multimedia_extensions.insert("MP2"); - multimedia_extensions.insert("MP3"); - multimedia_extensions.insert("MP4"); - multimedia_extensions.insert("MPC"); - multimedia_extensions.insert("MPE"); - multimedia_extensions.insert("MPEG"); - multimedia_extensions.insert("MPG"); - multimedia_extensions.insert("MPP"); - multimedia_extensions.insert("OGG"); - multimedia_extensions.insert("OGM"); - multimedia_extensions.insert("OGV"); - multimedia_extensions.insert("QT"); - multimedia_extensions.insert("RA"); - multimedia_extensions.insert("RAM"); - multimedia_extensions.insert("RM"); - multimedia_extensions.insert("RMV"); - multimedia_extensions.insert("RMVB"); - multimedia_extensions.insert("SWA"); - multimedia_extensions.insert("SWF"); - multimedia_extensions.insert("VOB"); - multimedia_extensions.insert("WAV"); - multimedia_extensions.insert("WMA"); - multimedia_extensions.insert("WMV"); - } +bool misc::isPreviewable(const QString& extension) +{ + static QSet multimedia_extensions; + if (multimedia_extensions.empty()) { + multimedia_extensions.insert("3GP"); + multimedia_extensions.insert("AAC"); + multimedia_extensions.insert("AC3"); + multimedia_extensions.insert("AIF"); + multimedia_extensions.insert("AIFC"); + multimedia_extensions.insert("AIFF"); + multimedia_extensions.insert("ASF"); + multimedia_extensions.insert("AU"); + multimedia_extensions.insert("AVI"); + multimedia_extensions.insert("FLAC"); + multimedia_extensions.insert("FLV"); + multimedia_extensions.insert("M3U"); + multimedia_extensions.insert("M4A"); + multimedia_extensions.insert("M4P"); + multimedia_extensions.insert("M4V"); + multimedia_extensions.insert("MID"); + multimedia_extensions.insert("MKV"); + multimedia_extensions.insert("MOV"); + multimedia_extensions.insert("MP2"); + multimedia_extensions.insert("MP3"); + multimedia_extensions.insert("MP4"); + multimedia_extensions.insert("MPC"); + multimedia_extensions.insert("MPE"); + multimedia_extensions.insert("MPEG"); + multimedia_extensions.insert("MPG"); + multimedia_extensions.insert("MPP"); + multimedia_extensions.insert("OGG"); + multimedia_extensions.insert("OGM"); + multimedia_extensions.insert("OGV"); + multimedia_extensions.insert("QT"); + multimedia_extensions.insert("RA"); + multimedia_extensions.insert("RAM"); + multimedia_extensions.insert("RM"); + multimedia_extensions.insert("RMV"); + multimedia_extensions.insert("RMVB"); + multimedia_extensions.insert("SWA"); + multimedia_extensions.insert("SWF"); + multimedia_extensions.insert("VOB"); + multimedia_extensions.insert("WAV"); + multimedia_extensions.insert("WMA"); + multimedia_extensions.insert("WMV"); + } - if (extension.isEmpty()) - return false; + if (extension.isEmpty()) + return false; - return multimedia_extensions.contains(extension.toUpper()); + return multimedia_extensions.contains(extension.toUpper()); } -QString misc::bcLinkToMagnet(QString bc_link) { - QByteArray raw_bc = bc_link.toUtf8(); - raw_bc = raw_bc.mid(8); // skip bc://bt/ - raw_bc = QByteArray::fromBase64(raw_bc); // Decode base64 - // Format is now AA/url_encoded_filename/size_bytes/info_hash/ZZ - QStringList parts = QString(raw_bc).split("/"); - if (parts.size() != 5) return QString::null; - QString filename = parts.at(1); - QString hash = parts.at(3); - QString magnet = "magnet:?xt=urn:btih:" + hash; - magnet += "&dn=" + filename; - return magnet; +QString misc::bcLinkToMagnet(QString bc_link) +{ + QByteArray raw_bc = bc_link.toUtf8(); + raw_bc = raw_bc.mid(8); // skip bc://bt/ + raw_bc = QByteArray::fromBase64(raw_bc); // Decode base64 + // Format is now AA/url_encoded_filename/size_bytes/info_hash/ZZ + QStringList parts = QString(raw_bc).split("/"); + if (parts.size() != 5) return QString::null; + QString filename = parts.at(1); + QString hash = parts.at(3); + QString magnet = "magnet:?xt=urn:btih:" + hash; + magnet += "&dn=" + filename; + return magnet; } -QString misc::magnetUriToName(const QString& magnet_uri) { - QString name = ""; - QRegExp regHex("dn=([^&]+)"); - const int pos = regHex.indexIn(magnet_uri); - if (pos > -1) { - const QString found = regHex.cap(1); - // URL decode - name = QUrl::fromPercentEncoding(found.toLocal8Bit()).replace("+", " "); - } - return name; +QString misc::magnetUriToName(const QString& magnet_uri) +{ + QString name = ""; + QRegExp regHex("dn=([^&]+)"); + const int pos = regHex.indexIn(magnet_uri); + if (pos > -1) { + const QString found = regHex.cap(1); + // URL decode + name = QUrl::fromPercentEncoding(found.toLocal8Bit()).replace("+", " "); + } + return name; } QList misc::magnetUriToTrackers(const QString& magnet_uri) { - QList trackers; - QRegExp rx("tr=([^&]+)"); - int pos = 0; + QList trackers; + QRegExp rx("tr=([^&]+)"); + int pos = 0; - while ((pos = rx.indexIn(magnet_uri, pos)) != -1) { - const QUrl tracker = QUrl::fromEncoded(rx.cap(1).toUtf8()); - qDebug() << Q_FUNC_INFO << "Found tracker: " << tracker.toString(); - trackers << tracker; - pos += rx.matchedLength(); - } + while ((pos = rx.indexIn(magnet_uri, pos)) != -1) { + const QUrl tracker = QUrl::fromEncoded(rx.cap(1).toUtf8()); + qDebug() << Q_FUNC_INFO << "Found tracker: " << tracker.toString(); + trackers << tracker; + pos += rx.matchedLength(); + } - return trackers; + return trackers; } -QString misc::magnetUriToHash(const QString& magnet_uri) { - QString hash = ""; - QRegExp regHex("urn:btih:([0-9A-Za-z]+)"); - // Hex - int pos = regHex.indexIn(magnet_uri); - if (pos > -1) { - const QString found = regHex.cap(1); - qDebug() << Q_FUNC_INFO << "regex found: " << found; - if (found.length() == 40) { - const sha1_hash sha1(QByteArray::fromHex(found.toLatin1()).constData()); - qDebug("magnetUriToHash (Hex): hash: %s", qPrintable(misc::toQString(sha1))); - return misc::toQString(sha1); +QString misc::magnetUriToHash(const QString& magnet_uri) +{ + QString hash = ""; + QRegExp regHex("urn:btih:([0-9A-Za-z]+)"); + // Hex + int pos = regHex.indexIn(magnet_uri); + if (pos > -1) { + const QString found = regHex.cap(1); + qDebug() << Q_FUNC_INFO << "regex found: " << found; + if (found.length() == 40) { + const sha1_hash sha1(QByteArray::fromHex(found.toLatin1()).constData()); + qDebug("magnetUriToHash (Hex): hash: %s", qPrintable(misc::toQString(sha1))); + return misc::toQString(sha1); + } } - } - // Base 32 - QRegExp regBase32("urn:btih:([A-Za-z2-7=]+)"); - pos = regBase32.indexIn(magnet_uri); - if (pos > -1) { - const QString found = regBase32.cap(1); - if (found.length() > 20 && (found.length()*5)%40 == 0) { - const sha1_hash sha1(base32decode(regBase32.cap(1).toStdString())); - hash = misc::toQString(sha1); + // Base 32 + QRegExp regBase32("urn:btih:([A-Za-z2-7=]+)"); + pos = regBase32.indexIn(magnet_uri); + if (pos > -1) { + const QString found = regBase32.cap(1); + if (found.length() > 20 && (found.length() * 5) % 40 == 0) { + const sha1_hash sha1(base32decode(regBase32.cap(1).toStdString())); + hash = misc::toQString(sha1); + } } - } - qDebug("magnetUriToHash (base32): hash: %s", qPrintable(hash)); - return hash; + qDebug("magnetUriToHash (base32): hash: %s", qPrintable(hash)); + return hash; } // Take a number of seconds and return an user-friendly // time duration like "1d 2h 10m". -QString misc::userFriendlyDuration(qlonglong seconds) { - if (seconds < 0 || seconds >= MAX_ETA) { +QString misc::userFriendlyDuration(qlonglong seconds) +{ + if (seconds < 0 || seconds >= MAX_ETA) + return QString::fromUtf8("∞"); + if (seconds == 0) + return "0"; + if (seconds < 60) + return QCoreApplication::translate("misc", "< 1m", "< 1 minute"); + int minutes = seconds / 60; + if (minutes < 60) + return QCoreApplication::translate("misc", "%1m","e.g: 10minutes").arg(QString::number(minutes)); + int hours = minutes / 60; + minutes = minutes - hours * 60; + if (hours < 24) + return QCoreApplication::translate("misc", "%1h %2m", "e.g: 3hours 5minutes").arg(QString::number(hours)).arg(QString::number(minutes)); + int days = hours / 24; + hours = hours - days * 24; + if (days < 100) + return QCoreApplication::translate("misc", "%1d %2h", "e.g: 2days 10hours").arg(QString::number(days)).arg(QString::number(hours)); return QString::fromUtf8("∞"); - } - if (seconds == 0) { - return "0"; - } - if (seconds < 60) { - return QCoreApplication::translate("misc", "< 1m", "< 1 minute"); - } - int minutes = seconds / 60; - if (minutes < 60) { - return QCoreApplication::translate("misc", "%1m","e.g: 10minutes").arg(QString::number(minutes)); - } - int hours = minutes / 60; - minutes = minutes - hours*60; - if (hours < 24) { - return QCoreApplication::translate("misc", "%1h %2m", "e.g: 3hours 5minutes").arg(QString::number(hours)).arg(QString::number(minutes)); - } - int days = hours / 24; - hours = hours - days * 24; - if (days < 100) { - return QCoreApplication::translate("misc", "%1d %2h", "e.g: 2days 10hours").arg(QString::number(days)).arg(QString::number(hours)); - } - return QString::fromUtf8("∞"); } -QString misc::getUserIDString() { - QString uid = "0"; +QString misc::getUserIDString() +{ + QString uid = "0"; #ifdef Q_OS_WIN - char buffer[UNLEN+1] = {0}; - DWORD buffer_len = UNLEN + 1; - if (!GetUserNameA(buffer, &buffer_len)) - uid = QString(buffer); + char buffer[UNLEN + 1] = {0}; + DWORD buffer_len = UNLEN + 1; + if (!GetUserNameA(buffer, &buffer_len)) + uid = QString(buffer); #else - uid = QString::number(getuid()); + uid = QString::number(getuid()); #endif - return uid; + return uid; } -QStringList misc::toStringList(const QList &l) { - QStringList ret; - foreach (const bool &b, l) { - ret << (b ? "1" : "0"); - } - return ret; +QStringList misc::toStringList(const QList &l) +{ + QStringList ret; + foreach (const bool &b, l) + ret << (b ? "1" : "0"); + return ret; } -QList misc::intListfromStringList(const QStringList &l) { - QList ret; - foreach (const QString &s, l) { - ret << s.toInt(); - } - return ret; +QList misc::intListfromStringList(const QStringList &l) +{ + QList ret; + foreach (const QString &s, l) + ret << s.toInt(); + return ret; } -QList misc::boolListfromStringList(const QStringList &l) { - QList ret; - foreach (const QString &s, l) { - ret << (s=="1"); - } - return ret; +QList misc::boolListfromStringList(const QStringList &l) +{ + QList ret; + foreach (const QString &s, l) + ret << (s=="1"); + return ret; } bool misc::isUrl(const QString &s) { - const QString scheme = QUrl(s).scheme(); - QRegExp is_url("http[s]?|ftp", Qt::CaseInsensitive); - return is_url.exactMatch(scheme); + 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 result = raw_text; - static QRegExp reURL( - "(\\s|^)" //start with whitespace or beginning of line - "(" - "(" //case 1 -- URL with scheme - "(http(s?))\\://" //start with scheme - "([a-zA-Z0-9_-]+\\.)+" // domainpart. at least one of these must exist - "([a-zA-Z0-9\\?%=&/_\\.:#;-]+)" // everything to 1st non-URI char, must be at least one char after the previous dot (cannot use ".*" because it can be too greedy) - ")" - "|" - "(" //case 2a -- no scheme, contains common TLD example.com - "([a-zA-Z0-9_-]+\\.)+" // domainpart. at least one of these must exist - "(?=" // must be followed by TLD - "AERO|aero|" //N.B. assertions are non-capturing - "ARPA|arpa|" - "ASIA|asia|" - "BIZ|biz|" - "CAT|cat|" - "COM|com|" - "COOP|coop|" - "EDU|edu|" - "GOV|gov|" - "INFO|info|" - "INT|int|" - "JOBS|jobs|" - "MIL|mil|" - "MOBI|mobi|" - "MUSEUM|museum|" - "NAME|name|" - "NET|net|" - "ORG|org|" - "PRO|pro|" - "RO|ro|" - "RU|ru|" - "TEL|tel|" - "TRAVEL|travel" - ")" - "([a-zA-Z0-9\\?%=&/_\\.:#;-]+)" // everything to 1st non-URI char, must be at least one char after the previous dot (cannot use ".*" because it can be too greedy) - ")" - "|" - "(" // case 2b no scheme, no TLD, must have at least 2 aphanum strings plus uncommon TLD string --> del.icio.us - "([a-zA-Z0-9_-]+\\.) {2,}" //2 or more domainpart. --> del.icio. - "[a-zA-Z]{2,}" //one ab (2 char or longer) --> us - "([a-zA-Z0-9\\?%=&/_\\.:#;-]*)" // everything to 1st non-URI char, maybe nothing in case of del.icio.us/path - ")" - ")" - ); + QString result = raw_text; + static QRegExp reURL( + "(\\s|^)" //start with whitespace or beginning of line + "(" + "(" //case 1 -- URL with scheme + "(http(s?))\\://" //start with scheme + "([a-zA-Z0-9_-]+\\.)+" // domainpart. at least one of these must exist + "([a-zA-Z0-9\\?%=&/_\\.:#;-]+)" // everything to 1st non-URI char, must be at least one char after the previous dot (cannot use ".*" because it can be too greedy) + ")" + "|" + "(" //case 2a -- no scheme, contains common TLD example.com + "([a-zA-Z0-9_-]+\\.)+" // domainpart. at least one of these must exist + "(?=" // must be followed by TLD + "AERO|aero|" //N.B. assertions are non-capturing + "ARPA|arpa|" + "ASIA|asia|" + "BIZ|biz|" + "CAT|cat|" + "COM|com|" + "COOP|coop|" + "EDU|edu|" + "GOV|gov|" + "INFO|info|" + "INT|int|" + "JOBS|jobs|" + "MIL|mil|" + "MOBI|mobi|" + "MUSEUM|museum|" + "NAME|name|" + "NET|net|" + "ORG|org|" + "PRO|pro|" + "RO|ro|" + "RU|ru|" + "TEL|tel|" + "TRAVEL|travel" + ")" + "([a-zA-Z0-9\\?%=&/_\\.:#;-]+)" // everything to 1st non-URI char, must be at least one char after the previous dot (cannot use ".*" because it can be too greedy) + ")" + "|" + "(" // case 2b no scheme, no TLD, must have at least 2 aphanum strings plus uncommon TLD string --> del.icio.us + "([a-zA-Z0-9_-]+\\.) {2,}" //2 or more domainpart. --> del.icio. + "[a-zA-Z]{2,}" //one ab (2 char or longer) --> us + "([a-zA-Z0-9\\?%=&/_\\.:#;-]*)" // everything to 1st non-URI char, maybe nothing in case of del.icio.us/path + ")" + ")" + ); - // Capture links - result.replace(reURL, "\\1\\2"); + // Capture links + result.replace(reURL, "\\1\\2"); - // Capture links without scheme - static QRegExp reNoScheme(""); - result.replace(reNoScheme, ""); + // Capture links without scheme + static QRegExp reNoScheme(""); + result.replace(reNoScheme, ""); - return result; + return result; } QString misc::toQString(time_t t) { - return QDateTime::fromTime_t(t).toString(Qt::DefaultLocaleLongDate); + return QDateTime::fromTime_t(t).toString(Qt::DefaultLocaleLongDate); } #ifndef DISABLE_GUI -bool misc::naturalSort(QString left, QString right, bool &result) { // uses lessThan comparison - // Return value indicates if functions was successful +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 + 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 + 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 (leftCharIsDigit) + break; // Both are digit, break this loop and compare numbers - if (leftChar != rightChar) - return false; // Strings' subsets before digit do not match + if (leftChar != rightChar) + return false; // Strings' subsets before digit do not match - ++posL; - ++posR; - } + ++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(); + 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(); + 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; - } + if (numL != numR) { + result = (numL < numR); + return true; + } - // Strings + digits do match and we haven't hit string end - // Do another round + // Strings + digits do match and we haven't hit string end + // Do another round - } while (true); + } while (true); - return false; + return false; } #endif // to send numbers instead of strings with suffixes -QString misc::accurateDoubleToString(const double &n, const 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. */ +QString misc::accurateDoubleToString(const double &n, const 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); + 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 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]; + int diff = lengthA ^ lengthB; + for(int i = 0; i < lengthA && i < lengthB; i++) + diff |= a[i] ^ b[i]; - return (diff == 0); + return (diff == 0); } void misc::loadBencodedFile(const QString &filename, std::vector &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec) @@ -669,16 +674,17 @@ void misc::loadBencodedFile(const QString &filename, std::vector &buffer, } namespace { - // Trick to get a portable sleep() function - class SleeperThread : public QThread { - public: +// Trick to get a portable sleep() function +class SleeperThread: public QThread { +public: static void msleep(unsigned long msecs) { - QThread::msleep(msecs); + QThread::msleep(msecs); } - }; +}; } -void misc::msleep(unsigned long msecs) { - SleeperThread::msleep(msecs); +void misc::msleep(unsigned long msecs) +{ + SleeperThread::msleep(msecs); } diff --git a/src/misc.h b/src/misc.h index b4e762847..4d7461983 100644 --- a/src/misc.h +++ b/src/misc.h @@ -48,12 +48,12 @@ namespace libtorrent { #if LIBTORRENT_VERSION_NUM < 10000 - class big_number; - typedef big_number sha1_hash; + class big_number; + typedef big_number sha1_hash; #else - class sha1_hash; + class sha1_hash; #endif - struct lazy_entry; + struct lazy_entry; } const qlonglong MAX_ETA = 8640000; @@ -62,58 +62,58 @@ enum shutDownAction { NO_SHUTDOWN, SHUTDOWN_COMPUTER, SUSPEND_COMPUTER, HIBERNAT /* Miscellaneaous functions that can be useful */ namespace misc { - QString toQString(const std::string &str); - QString toQString(const char* str); - QString toQStringU(const std::string &str); - QString toQStringU(const char* str); - QString toQString(const libtorrent::sha1_hash &hash); + QString toQString(const std::string &str); + QString toQString(const char* str); + QString toQStringU(const std::string &str); + QString toQStringU(const char* str); + QString toQString(const libtorrent::sha1_hash &hash); #ifndef DISABLE_GUI - void shutdownComputer(shutDownAction action=SHUTDOWN_COMPUTER); + void shutdownComputer(shutDownAction action = SHUTDOWN_COMPUTER); #endif - QString parseHtmlLinks(const QString &raw_text); + QString parseHtmlLinks(const QString &raw_text); - bool isUrl(const QString &s); + bool isUrl(const QString &s); #ifndef DISABLE_GUI - // Get screen center - QPoint screenCenter(QWidget *win); + // 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 magnetUriToName(const QString& magnet_uri); - QString magnetUriToHash(const QString& magnet_uri); - QList magnetUriToTrackers(const QString& magnet_uri); - 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(); + 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 magnetUriToName(const QString& magnet_uri); + QString magnetUriToHash(const QString& magnet_uri); + QList magnetUriToTrackers(const QString& magnet_uri); + 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 &l); - QList intListfromStringList(const QStringList &l); - QList boolListfromStringList(const QStringList &l); + // Convert functions + QStringList toStringList(const QList &l); + QList intListfromStringList(const QStringList &l); + QList boolListfromStringList(const QStringList &l); - QString toQString(time_t t); - QString accurateDoubleToString(const double &n, const int &precision); + QString toQString(time_t t); + QString accurateDoubleToString(const double &n, const int &precision); #ifndef DISABLE_GUI - bool naturalSort(QString left, QString right, bool& result); + 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 loadBencodedFile(const QString &filename, std::vector &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec); + // 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 loadBencodedFile(const QString &filename, std::vector &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec); - void msleep(unsigned long msecs); + void msleep(unsigned long msecs); } #endif diff --git a/src/torrentimportdlg.cpp b/src/torrentimportdlg.cpp index 0ada519d1..5b2820d5b 100644 --- a/src/torrentimportdlg.cpp +++ b/src/torrentimportdlg.cpp @@ -42,175 +42,177 @@ using namespace libtorrent; -TorrentImportDlg::TorrentImportDlg(QWidget *parent) : - QDialog(parent), - ui(new Ui::TorrentImportDlg) +TorrentImportDlg::TorrentImportDlg(QWidget *parent): + QDialog(parent), + ui(new Ui::TorrentImportDlg) { - ui->setupUi(this); - // Icons - ui->lbl_info->setPixmap(IconProvider::instance()->getIcon("dialog-information").pixmap(ui->lbl_info->height())); - ui->lbl_info->setFixedWidth(ui->lbl_info->height()); - ui->importBtn->setIcon(IconProvider::instance()->getIcon("document-import")); - // Libtorrent < 0.15 does not support skipping file checking - loadSettings(); + ui->setupUi(this); + // Icons + ui->lbl_info->setPixmap(IconProvider::instance()->getIcon("dialog-information").pixmap(ui->lbl_info->height())); + ui->lbl_info->setFixedWidth(ui->lbl_info->height()); + ui->importBtn->setIcon(IconProvider::instance()->getIcon("document-import")); + // Libtorrent < 0.15 does not support skipping file checking + loadSettings(); } TorrentImportDlg::~TorrentImportDlg() { - delete ui; + delete ui; } void TorrentImportDlg::on_browseTorrentBtn_clicked() { - const QString default_dir = Preferences::instance()->getMainLastDir(); - // Ask for a torrent file - m_torrentPath = QFileDialog::getOpenFileName(this, tr("Torrent file to import"), default_dir, tr("Torrent files")+QString(" (*.torrent)")); - if (!m_torrentPath.isEmpty()) { - loadTorrent(m_torrentPath); - } else { - ui->lineTorrent->clear(); - } + const QString default_dir = Preferences::instance()->getMainLastDir(); + // Ask for a torrent file + m_torrentPath = QFileDialog::getOpenFileName(this, tr("Torrent file to import"), default_dir, tr("Torrent files") + QString(" (*.torrent)")); + if (!m_torrentPath.isEmpty()) + loadTorrent(m_torrentPath); + else + ui->lineTorrent->clear(); } void TorrentImportDlg::on_browseContentBtn_clicked() { - const QString default_dir = Preferences::instance()->getTorImportLastContentDir(); - // Test for multi-file taken from libtorrent/create_torrent.hpp -> create_torrent::create_torrent - bool multifile = t->num_files() > 1; + const QString default_dir = Preferences::instance()->getTorImportLastContentDir(); + // Test for multi-file taken from libtorrent/create_torrent.hpp -> create_torrent::create_torrent + bool multifile = t->num_files() > 1; #if LIBTORRENT_VERSION_NUM >= 1600 - if (!multifile && has_parent_path(t->files().file_path(*(t->files().begin())))) - multifile = true; + if (!multifile && has_parent_path(t->files().file_path(*(t->files().begin())))) + multifile = true; #else - if (!multifile && t->file_at(0).path.has_parent_path()) - multifile = true; + if (!multifile && t->file_at(0).path.has_parent_path()) + multifile = true; #endif - if (!multifile) { - // Single file torrent - const QString file_name = fsutils::fileName(misc::toQStringU(t->file_at(0).path)); - qDebug("Torrent has only one file: %s", qPrintable(file_name)); - QString extension = fsutils::fileExtension(file_name); - qDebug("File extension is : %s", qPrintable(extension)); - QString filter; - if (!extension.isEmpty()) { - extension = extension.toUpper(); - filter = tr("%1 Files", "%1 is a file extension (e.g. PDF)").arg(extension)+" (*."+extension+")"; + if (!multifile) { + // Single file torrent + const QString file_name = fsutils::fileName(misc::toQStringU(t->file_at(0).path)); + qDebug("Torrent has only one file: %s", qPrintable(file_name)); + QString extension = fsutils::fileExtension(file_name); + qDebug("File extension is : %s", qPrintable(extension)); + QString filter; + if (!extension.isEmpty()) { + extension = extension.toUpper(); + filter = tr("%1 Files", "%1 is a file extension (e.g. PDF)").arg(extension) + " (*." + extension + ")"; + } + m_contentPath = QFileDialog::getOpenFileName(this, tr("Please provide the location of %1", "%1 is a file name").arg(file_name), default_dir, filter); + if (m_contentPath.isEmpty() || !QFile(m_contentPath).exists()) { + m_contentPath = QString::null; + ui->importBtn->setEnabled(false); + ui->checkSkipCheck->setEnabled(false); + return; + } + // Update display + ui->lineContent->setText(fsutils::toNativePath(m_contentPath)); + // Check file size + const qint64 file_size = QFile(m_contentPath).size(); + if (t->file_at(0).size == file_size) { + qDebug("The file size matches, allowing fast seeding..."); + ui->checkSkipCheck->setEnabled(true); + } + else { + qDebug("The file size does not match, forbidding fast seeding..."); + ui->checkSkipCheck->setChecked(false); + ui->checkSkipCheck->setEnabled(false); + } + // Handle file renaming + QStringList parts = m_contentPath.split("/"); + QString new_file_name = parts.takeLast(); + if (new_file_name != file_name) { + qDebug("The file has been renamed"); + QStringList new_parts = m_filesPath.first().split("/"); + new_parts.replace(new_parts.count() - 1, new_file_name); + m_filesPath.replace(0, new_parts.join("/")); + } + m_contentPath = parts.join("/"); } - m_contentPath = QFileDialog::getOpenFileName(this, tr("Please provide the location of %1", "%1 is a file name").arg(file_name), default_dir, filter); - if (m_contentPath.isEmpty() || !QFile(m_contentPath).exists()) { - m_contentPath = QString::null; - ui->importBtn->setEnabled(false); - ui->checkSkipCheck->setEnabled(false); - return; + else { + // multiple files torrent + m_contentPath = QFileDialog::getExistingDirectory(this, tr("Please point to the location of the torrent: %1").arg(misc::toQStringU(t->name())), + default_dir); + if (m_contentPath.isEmpty() || !QDir(m_contentPath).exists()) { + m_contentPath = QString::null; + ui->importBtn->setEnabled(false); + ui->checkSkipCheck->setEnabled(false); + return; + } + // Update the display + ui->lineContent->setText(fsutils::toNativePath(m_contentPath)); + bool size_mismatch = false; + QDir content_dir(m_contentPath); + content_dir.cdUp(); + // Check file sizes + for (int i = 0; inum_files(); ++i) { + const QString rel_path = misc::toQStringU(t->file_at(i).path); + if (QFile(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))).size() != t->file_at(i).size) { + qDebug("%s is %lld", + qPrintable(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))), (long long int) QFile(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))).size()); + qDebug("%s is %lld", + qPrintable(rel_path), (long long int)t->file_at(i).size); + size_mismatch = true; + break; + } + } + if (size_mismatch) { + qDebug("The file size does not match, forbidding fast seeding..."); + ui->checkSkipCheck->setChecked(false); + ui->checkSkipCheck->setEnabled(false); + } + else { + qDebug("The file size matches, allowing fast seeding..."); + ui->checkSkipCheck->setEnabled(true); + } } - // Update display - ui->lineContent->setText(fsutils::toNativePath(m_contentPath)); - // Check file size - const qint64 file_size = QFile(m_contentPath).size(); - if (t->file_at(0).size == file_size) { - qDebug("The file size matches, allowing fast seeding..."); - ui->checkSkipCheck->setEnabled(true); - } else { - qDebug("The file size does not match, forbidding fast seeding..."); - ui->checkSkipCheck->setChecked(false); - ui->checkSkipCheck->setEnabled(false); - } - // Handle file renaming - QStringList parts = m_contentPath.split("/"); - QString new_file_name = parts.takeLast(); - if (new_file_name != file_name) { - qDebug("The file has been renamed"); - QStringList new_parts = m_filesPath.first().split("/"); - new_parts.replace(new_parts.count()-1, new_file_name); - m_filesPath.replace(0, new_parts.join("/")); - } - m_contentPath = parts.join("/"); - } else { - // multiple files torrent - m_contentPath = QFileDialog::getExistingDirectory(this, tr("Please point to the location of the torrent: %1").arg(misc::toQStringU(t->name())), - default_dir); - if (m_contentPath.isEmpty() || !QDir(m_contentPath).exists()) { - m_contentPath = QString::null; - ui->importBtn->setEnabled(false); - ui->checkSkipCheck->setEnabled(false); - return; - } - // Update the display - ui->lineContent->setText(fsutils::toNativePath(m_contentPath)); - bool size_mismatch = false; - QDir content_dir(m_contentPath); - content_dir.cdUp(); - // Check file sizes - for (int i=0; inum_files(); ++i) { - const QString rel_path = misc::toQStringU(t->file_at(i).path); - if (QFile(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))).size() != t->file_at(i).size) { - qDebug("%s is %lld", - qPrintable(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))), (long long int) QFile(fsutils::expandPath(content_dir.absoluteFilePath(rel_path))).size()); - qDebug("%s is %lld", - qPrintable(rel_path), (long long int)t->file_at(i).size); - size_mismatch = true; - break; - } - } - if (size_mismatch) { - qDebug("The file size does not match, forbidding fast seeding..."); - ui->checkSkipCheck->setChecked(false); - ui->checkSkipCheck->setEnabled(false); - } else { - qDebug("The file size matches, allowing fast seeding..."); - ui->checkSkipCheck->setEnabled(true); - } - } - // Enable the import button - ui->importBtn->setEnabled(true); + // Enable the import button + ui->importBtn->setEnabled(true); } void TorrentImportDlg::on_importBtn_clicked() { - saveSettings(); - // Has to be accept() and not close() - // or the torrent won't be imported - accept(); + saveSettings(); + // Has to be accept() and not close() + // or the torrent won't be imported + accept(); } QString TorrentImportDlg::getTorrentPath() const { - return m_torrentPath; + return m_torrentPath; } QString TorrentImportDlg::getContentPath() const { - return m_contentPath; + return m_contentPath; } void TorrentImportDlg::importTorrent() { - qDebug() << Q_FUNC_INFO << "ENTER"; - TorrentImportDlg dlg; - if (dlg.exec()) { - qDebug() << "Loading the torrent file..."; - boost::intrusive_ptr t = dlg.torrent(); - if (!t->is_valid()) - return; - QString torrent_path = dlg.getTorrentPath(); - QString content_path = dlg.getContentPath(); - if (torrent_path.isEmpty() || content_path.isEmpty() || !QFile(torrent_path).exists()) { - qWarning() << "Incorrect input, aborting." << torrent_path << content_path; - return; + qDebug() << Q_FUNC_INFO << "ENTER"; + TorrentImportDlg dlg; + if (dlg.exec()) { + qDebug() << "Loading the torrent file..."; + boost::intrusive_ptr t = dlg.torrent(); + if (!t->is_valid()) + return; + QString torrent_path = dlg.getTorrentPath(); + QString content_path = dlg.getContentPath(); + if (torrent_path.isEmpty() || content_path.isEmpty() || !QFile(torrent_path).exists()) { + qWarning() << "Incorrect input, aborting." << torrent_path << content_path; + return; + } + const QString hash = misc::toQString(t->info_hash()); + qDebug() << "Torrent hash is" << hash; + TorrentTempData::setSavePath(hash, content_path); + TorrentTempData::setSeedingMode(hash, dlg.skipFileChecking()); + qDebug("Adding the torrent to the session..."); + QBtSession::instance()->addTorrent(torrent_path, false, QString(), false, true); + // Remember the last opened folder + Preferences* const pref = Preferences::instance(); + pref->setMainLastDir(fsutils::fromNativePath(torrent_path)); + pref->setTorImportLastContentDir(fsutils::fromNativePath(content_path)); + return; } - const QString hash = misc::toQString(t->info_hash()); - qDebug() << "Torrent hash is" << hash; - TorrentTempData::setSavePath(hash, content_path); - TorrentTempData::setSeedingMode(hash, dlg.skipFileChecking()); - qDebug("Adding the torrent to the session..."); - QBtSession::instance()->addTorrent(torrent_path, false, QString(), false, true); - // Remember the last opened folder - Preferences* const pref = Preferences::instance(); - pref->setMainLastDir(fsutils::fromNativePath(torrent_path)); - pref->setTorImportLastContentDir(fsutils::fromNativePath(content_path)); + qDebug() << Q_FUNC_INFO << "EXIT"; return; - } - qDebug() << Q_FUNC_INFO << "EXIT"; - return; } void TorrentImportDlg::loadTorrent(const QString &torrent_path) @@ -240,42 +242,41 @@ void TorrentImportDlg::loadTorrent(const QString &torrent_path) void TorrentImportDlg::initializeFilesPath() { - m_filesPath.clear(); - // Loads files path in the torrent - for (int i=0; inum_files(); ++i) { - m_filesPath << fsutils::fromNativePath(misc::toQStringU(t->file_at(i).path)); - } + m_filesPath.clear(); + // Loads files path in the torrent + for (int i = 0; inum_files(); ++i) + m_filesPath << fsutils::fromNativePath(misc::toQStringU(t->file_at(i).path)); } bool TorrentImportDlg::fileRenamed() const { - return m_fileRenamed; + return m_fileRenamed; } boost::intrusive_ptr TorrentImportDlg::torrent() const { - return t; + return t; } bool TorrentImportDlg::skipFileChecking() const { - return ui->checkSkipCheck->isChecked(); + return ui->checkSkipCheck->isChecked(); } void TorrentImportDlg::loadSettings() { - restoreGeometry(Preferences::instance()->getTorImportGeometry()); + restoreGeometry(Preferences::instance()->getTorImportGeometry()); } void TorrentImportDlg::saveSettings() { - Preferences::instance()->setTorImportGeometry(saveGeometry()); + Preferences::instance()->setTorImportGeometry(saveGeometry()); } void TorrentImportDlg::closeEvent(QCloseEvent *event) { - qDebug() << Q_FUNC_INFO; - saveSettings(); - QDialog::closeEvent(event); + qDebug() << Q_FUNC_INFO; + saveSettings(); + QDialog::closeEvent(event); } diff --git a/src/torrentimportdlg.h b/src/torrentimportdlg.h index bbb513581..4e0ff7640 100644 --- a/src/torrentimportdlg.h +++ b/src/torrentimportdlg.h @@ -39,51 +39,51 @@ QT_BEGIN_NAMESPACE namespace Ui { -class TorrentImportDlg; + class TorrentImportDlg; } QT_END_NAMESPACE class QBtSession; -class TorrentImportDlg : public QDialog +class TorrentImportDlg: public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit TorrentImportDlg(QWidget *parent = 0); - ~TorrentImportDlg(); - static void importTorrent(); - QString getTorrentPath() const; - QString getContentPath() const; - bool fileRenamed() const; - boost::intrusive_ptr torrent() const; - bool skipFileChecking() const; + explicit TorrentImportDlg(QWidget *parent = 0); + ~TorrentImportDlg(); + static void importTorrent(); + QString getTorrentPath() const; + QString getContentPath() const; + bool fileRenamed() const; + boost::intrusive_ptr torrent() const; + bool skipFileChecking() const; protected slots: - void loadTorrent(const QString &torrent_path); - void initializeFilesPath(); + void loadTorrent(const QString &torrent_path); + void initializeFilesPath(); private slots: - void on_browseTorrentBtn_clicked(); + void on_browseTorrentBtn_clicked(); - void on_browseContentBtn_clicked(); + void on_browseContentBtn_clicked(); - void on_importBtn_clicked(); + void on_importBtn_clicked(); protected: - void closeEvent(QCloseEvent *event); + void closeEvent(QCloseEvent *event); private: - void loadSettings(); - void saveSettings(); + void loadSettings(); + void saveSettings(); private: - Ui::TorrentImportDlg *ui; - boost::intrusive_ptr t; - QStringList m_filesPath; - QString m_contentPath; - QString m_torrentPath; - bool m_fileRenamed; + Ui::TorrentImportDlg *ui; + boost::intrusive_ptr t; + QStringList m_filesPath; + QString m_contentPath; + QString m_torrentPath; + bool m_fileRenamed; }; #endif // TORRENTIMPORTDLG_H