From 664479145881363cb64c352e3f61c6a6ab08b2b7 Mon Sep 17 00:00:00 2001 From: buinsky Date: Mon, 8 Dec 2014 04:40:58 +0300 Subject: [PATCH] Follow project coding style. Issue #2192. --- src/qtlibtorrent/qtorrenthandle.cpp | 853 +++++++------- src/qtlibtorrent/qtorrenthandle.h | 158 +-- src/transferlistwidget.cpp | 1598 ++++++++++++++------------- src/transferlistwidget.h | 115 +- src/webui/btjson.cpp | 25 +- src/webui/www/public/filters.html | 16 +- 6 files changed, 1426 insertions(+), 1339 deletions(-) diff --git a/src/qtlibtorrent/qtorrenthandle.cpp b/src/qtlibtorrent/qtorrenthandle.cpp index e81d0fa99..62b03ce5c 100644 --- a/src/qtlibtorrent/qtorrenthandle.cpp +++ b/src/qtlibtorrent/qtorrenthandle.cpp @@ -56,358 +56,395 @@ using namespace std; static QPair get_file_extremity_pieces(const torrent_info& t, int file_index) { - const int num_pieces = t.num_pieces(); - const int piece_size = t.piece_length(); - const file_entry& file = t.file_at(file_index); + const int num_pieces = t.num_pieces(); + const int piece_size = t.piece_length(); + const file_entry& file = t.file_at(file_index); - // Determine the first and last piece of the file - int first_piece = floor((file.offset + 1) / (float) piece_size); - Q_ASSERT(first_piece >= 0 && first_piece < num_pieces); - qDebug("First piece of the file is %d/%d", first_piece, num_pieces - 1); + // Determine the first and last piece of the file + int first_piece = floor((file.offset + 1) / (float) piece_size); + Q_ASSERT(first_piece >= 0 && first_piece < num_pieces); + qDebug("First piece of the file is %d/%d", first_piece, num_pieces - 1); - int num_pieces_in_file = ceil(file.size / (float) piece_size); - int last_piece = first_piece + num_pieces_in_file - 1; - Q_ASSERT(last_piece >= 0 && last_piece < num_pieces); - qDebug("last piece of the file is %d/%d", last_piece, num_pieces - 1); + int num_pieces_in_file = ceil(file.size / (float) piece_size); + int last_piece = first_piece + num_pieces_in_file - 1; + Q_ASSERT(last_piece >= 0 && last_piece < num_pieces); + qDebug("last piece of the file is %d/%d", last_piece, num_pieces - 1); - return qMakePair(first_piece, last_piece); + return qMakePair(first_piece, last_piece); } -QTorrentHandle::QTorrentHandle(const torrent_handle& h): torrent_handle(h) {} +QTorrentHandle::QTorrentHandle(const torrent_handle& h): torrent_handle(h) +{ +} // // Getters // -QString QTorrentHandle::hash() const { - return misc::toQString(torrent_handle::info_hash()); +QString QTorrentHandle::hash() const +{ + return misc::toQString(torrent_handle::info_hash()); } -QString QTorrentHandle::name() const { - QString name = TorrentPersistentData::getName(hash()); - if (name.isEmpty()) { +QString QTorrentHandle::name() const +{ + QString name = TorrentPersistentData::getName(hash()); + if (name.isEmpty()) { #if LIBTORRENT_VERSION_NUM < 10000 - name = misc::toQStringU(torrent_handle::name()); + name = misc::toQStringU(torrent_handle::name()); #else - name = misc::toQStringU(status(query_name).name); + name = misc::toQStringU(status(query_name).name); #endif - } - return name; + } + return name; } -QString QTorrentHandle::creation_date() const { +QString QTorrentHandle::creation_date() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - boost::optional t = torrent_handle::get_torrent_info().creation_date(); + boost::optional t = torrent_handle::get_torrent_info().creation_date(); #else - boost::optional t = torrent_handle::torrent_file()->creation_date(); + boost::optional t = torrent_handle::torrent_file()->creation_date(); #endif - return t ? misc::toQString(*t) : ""; + return t ? misc::toQString(*t) : ""; } -qlonglong QTorrentHandle::creation_date_unix() const { +qlonglong QTorrentHandle::creation_date_unix() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - boost::optional t = torrent_handle::get_torrent_info().creation_date(); + boost::optional t = torrent_handle::get_torrent_info().creation_date(); #else - boost::optional t = torrent_handle::torrent_file()->creation_date(); + boost::optional t = torrent_handle::torrent_file()->creation_date(); #endif - return t ? *t : -1; + return t ? *t : -1; } -QString QTorrentHandle::current_tracker() const { - return misc::toQString(status(0x0).current_tracker); +QString QTorrentHandle::current_tracker() const +{ + return misc::toQString(status(0x0).current_tracker); } -bool QTorrentHandle::is_paused() const { - return is_paused(status(0x0)); +bool QTorrentHandle::is_paused() const +{ + return is_paused(status(0x0)); } -bool QTorrentHandle::is_queued() const { - return is_queued(status(0x0)); +bool QTorrentHandle::is_queued() const +{ + return is_queued(status(0x0)); } -size_type QTorrentHandle::total_size() const { +size_type QTorrentHandle::total_size() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return torrent_handle::get_torrent_info().total_size(); + return torrent_handle::get_torrent_info().total_size(); #else - return torrent_handle::torrent_file()->total_size(); + return torrent_handle::torrent_file()->total_size(); #endif } -size_type QTorrentHandle::piece_length() const { +size_type QTorrentHandle::piece_length() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return torrent_handle::get_torrent_info().piece_length(); + return torrent_handle::get_torrent_info().piece_length(); #else - return torrent_handle::torrent_file()->piece_length(); + return torrent_handle::torrent_file()->piece_length(); #endif } -int QTorrentHandle::num_pieces() const { +int QTorrentHandle::num_pieces() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return torrent_handle::get_torrent_info().num_pieces(); + return torrent_handle::get_torrent_info().num_pieces(); #else - return torrent_handle::torrent_file()->num_pieces(); + return torrent_handle::torrent_file()->num_pieces(); #endif } -bool QTorrentHandle::first_last_piece_first() const { +bool QTorrentHandle::first_last_piece_first() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - torrent_info const* t = &get_torrent_info(); + torrent_info const* t = &get_torrent_info(); #else - boost::intrusive_ptr t = torrent_file(); + boost::intrusive_ptr t = torrent_file(); #endif - // Get int first media file - int index = 0; - for (index = 0; index < t->num_files(); ++index) { - QString path = misc::toQStringU(t->file_at(index).path); - const QString ext = fsutils::fileExtension(path); - if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) - break; - } + // Get int first media file + int index = 0; + for (index = 0; index < t->num_files(); ++index) { + QString path = misc::toQStringU(t->file_at(index).path); + const QString ext = fsutils::fileExtension(path); + if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) + break; + } - if (index >= t->num_files()) // No media file - return false; + if (index >= t->num_files()) // No media file + return false; + QPair extremities = get_file_extremity_pieces(*t, index); - QPair extremities = get_file_extremity_pieces(*t, index); - - return (torrent_handle::piece_priority(extremities.first) == 7) - && (torrent_handle::piece_priority(extremities.second) == 7); + return (torrent_handle::piece_priority(extremities.first) == 7) + && (torrent_handle::piece_priority(extremities.second) == 7); } -QString QTorrentHandle::save_path() const { +QString QTorrentHandle::save_path() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return fsutils::fromNativePath(misc::toQStringU(torrent_handle::save_path())); + return fsutils::fromNativePath(misc::toQStringU(torrent_handle::save_path())); #else - return fsutils::fromNativePath(misc::toQStringU(status(torrent_handle::query_save_path).save_path)); + return fsutils::fromNativePath(misc::toQStringU(status(torrent_handle::query_save_path).save_path)); #endif } -QString QTorrentHandle::save_path_parsed() const { +QString QTorrentHandle::save_path_parsed() const +{ QString p; if (has_metadata() && num_files() == 1) { - p = firstFileSavePath(); - } else { - p = fsutils::fromNativePath(TorrentPersistentData::getSavePath(hash())); - if (p.isEmpty()) - p = save_path(); + p = firstFileSavePath(); + } + else { + p = fsutils::fromNativePath(TorrentPersistentData::getSavePath(hash())); + if (p.isEmpty()) + p = save_path(); } return p; } -QStringList QTorrentHandle::url_seeds() const { - QStringList res; - try { - const std::set existing_seeds = torrent_handle::url_seeds(); +QStringList QTorrentHandle::url_seeds() const +{ + QStringList res; + try { + const std::set existing_seeds = torrent_handle::url_seeds(); - std::set::const_iterator it = existing_seeds.begin(); - std::set::const_iterator itend = existing_seeds.end(); - for ( ; it != itend; ++it) { - qDebug("URL Seed: %s", it->c_str()); - res << misc::toQString(*it); + std::set::const_iterator it = existing_seeds.begin(); + std::set::const_iterator itend = existing_seeds.end(); + for (; it != itend; ++it) { + qDebug("URL Seed: %s", it->c_str()); + res << misc::toQString(*it); + } + } catch(std::exception &e) { + std::cout << "ERROR: Failed to convert the URL seed" << std::endl; } - } catch(std::exception &e) { - std::cout << "ERROR: Failed to convert the URL seed" << std::endl; - } - return res; + return res; } // get the size of the torrent without the filtered files -size_type QTorrentHandle::actual_size() const { - return status(query_accurate_download_counters).total_wanted; +size_type QTorrentHandle::actual_size() const +{ + return status(query_accurate_download_counters).total_wanted; } -bool QTorrentHandle::has_filtered_pieces() const { - const std::vector piece_priorities = torrent_handle::piece_priorities(); - foreach (const int priority, piece_priorities) { - if (priority == 0) - return true; - } - return false; +bool QTorrentHandle::has_filtered_pieces() const +{ + const std::vector piece_priorities = torrent_handle::piece_priorities(); + foreach (const int priority, piece_priorities) + if (priority == 0) + return true; + return false; } -int QTorrentHandle::num_files() const { +int QTorrentHandle::num_files() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return torrent_handle::get_torrent_info().num_files(); + return torrent_handle::get_torrent_info().num_files(); #else - return torrent_handle::torrent_file()->num_files(); + return torrent_handle::torrent_file()->num_files(); #endif } -QString QTorrentHandle::filename_at(unsigned int index) const { +QString QTorrentHandle::filename_at(unsigned int index) const +{ #if LIBTORRENT_VERSION_NUM < 10000 - Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files()); + Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files()); #else - Q_ASSERT(index < (unsigned int)torrent_handle::torrent_file()->num_files()); + Q_ASSERT(index < (unsigned int)torrent_handle::torrent_file()->num_files()); #endif - return fsutils::fileName(filepath_at(index)); + return fsutils::fileName(filepath_at(index)); } -size_type QTorrentHandle::filesize_at(unsigned int index) const { +size_type QTorrentHandle::filesize_at(unsigned int index) const +{ #if LIBTORRENT_VERSION_NUM < 10000 - Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files()); - return torrent_handle::get_torrent_info().files().file_size(index); + Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files()); + return torrent_handle::get_torrent_info().files().file_size(index); #else - Q_ASSERT(index < (unsigned int)torrent_handle::torrent_file()->num_files()); - return torrent_handle::torrent_file()->files().file_size(index); + Q_ASSERT(index < (unsigned int)torrent_handle::torrent_file()->num_files()); + return torrent_handle::torrent_file()->files().file_size(index); #endif } -QString QTorrentHandle::filepath_at(unsigned int index) const { +QString QTorrentHandle::filepath_at(unsigned int index) const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return filepath_at(torrent_handle::get_torrent_info(), index); + return filepath_at(torrent_handle::get_torrent_info(), index); #else - return filepath_at(*torrent_handle::torrent_file(), index); + return filepath_at(*torrent_handle::torrent_file(), index); #endif } -QString QTorrentHandle::orig_filepath_at(unsigned int index) const { +QString QTorrentHandle::orig_filepath_at(unsigned int index) const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return fsutils::fromNativePath(misc::toQStringU(torrent_handle::get_torrent_info().orig_files().file_path(index))); + return fsutils::fromNativePath(misc::toQStringU(torrent_handle::get_torrent_info().orig_files().file_path(index))); #else - return fsutils::fromNativePath(misc::toQStringU(torrent_handle::torrent_file()->orig_files().file_path(index))); + return fsutils::fromNativePath(misc::toQStringU(torrent_handle::torrent_file()->orig_files().file_path(index))); #endif } -torrent_status::state_t QTorrentHandle::state() const { - return status(0x0).state; +torrent_status::state_t QTorrentHandle::state() const +{ + return status(0x0).state; } -QString QTorrentHandle::creator() const { +QString QTorrentHandle::creator() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return misc::toQStringU(torrent_handle::get_torrent_info().creator()); + return misc::toQStringU(torrent_handle::get_torrent_info().creator()); #else - return misc::toQStringU(torrent_handle::torrent_file()->creator()); + return misc::toQStringU(torrent_handle::torrent_file()->creator()); #endif } -QString QTorrentHandle::comment() const { +QString QTorrentHandle::comment() const +{ #if LIBTORRENT_VERSION_NUM < 10000 - return misc::toQStringU(torrent_handle::get_torrent_info().comment()); + return misc::toQStringU(torrent_handle::get_torrent_info().comment()); #else - return misc::toQStringU(torrent_handle::torrent_file()->comment()); + return misc::toQStringU(torrent_handle::torrent_file()->comment()); #endif } -bool QTorrentHandle::is_checking() const { - return is_checking(status(0x0)); +bool QTorrentHandle::is_checking() const +{ + return is_checking(status(0x0)); } // Return a list of absolute paths corresponding // to all files in a torrent -QStringList QTorrentHandle::absolute_files_path() const { - QDir saveDir(save_path()); - QStringList res; - for (int i = 0; i fp = torrent_handle::file_priorities(); - for (uint i = 0; i < fp.size(); ++i) { - if (fp[i] == 0) { - const QString file_path = fsutils::expandPathAbs(saveDir.absoluteFilePath(filepath_at(i))); - if (file_path.contains(".unwanted")) - res << file_path; +QStringList QTorrentHandle::absolute_files_path_uneeded() const +{ + QDir saveDir(save_path()); + QStringList res; + std::vector fp = torrent_handle::file_priorities(); + for (uint i = 0; i < fp.size(); ++i) { + if (fp[i] == 0) { + const QString file_path = fsutils::expandPathAbs(saveDir.absoluteFilePath(filepath_at(i))); + if (file_path.contains(".unwanted")) + res << file_path; + } } - } - return res; + return res; } -bool QTorrentHandle::has_missing_files() const { - const QStringList paths = absolute_files_path(); - foreach (const QString &path, paths) { - if (!QFile::exists(path)) return true; - } - return false; -} - -int QTorrentHandle::queue_position() const { - return queue_position(status(0x0)); -} - -bool QTorrentHandle::is_seed() const { - // Affected by bug http://code.rasterbar.com/libtorrent/ticket/402 - //return torrent_handle::is_seed(); - // May suffer from approximation problems - //return (progress() == 1.); - // This looks safe - return is_seed(status(0x0)); -} - -bool QTorrentHandle::is_sequential_download() const { - return status(0x0).sequential_download; -} - -bool QTorrentHandle::priv() const { - if (!has_metadata()) +bool QTorrentHandle::has_missing_files() const +{ + const QStringList paths = absolute_files_path(); + foreach (const QString &path, paths) + if (!QFile::exists(path)) return true; return false; +} + +int QTorrentHandle::queue_position() const +{ + return queue_position(status(0x0)); +} + +bool QTorrentHandle::is_seed() const +{ + // Affected by bug http://code.rasterbar.com/libtorrent/ticket/402 + //return torrent_handle::is_seed(); + // May suffer from approximation problems + //return (progress() == 1.); + // This looks safe + return is_seed(status(0x0)); +} + +bool QTorrentHandle::is_sequential_download() const +{ + return status(0x0).sequential_download; +} + +bool QTorrentHandle::priv() const +{ + if (!has_metadata()) + return false; #if LIBTORRENT_VERSION_NUM < 10000 - return torrent_handle::get_torrent_info().priv(); + return torrent_handle::get_torrent_info().priv(); #else - return torrent_handle::torrent_file()->priv(); + return torrent_handle::torrent_file()->priv(); #endif } -QString QTorrentHandle::firstFileSavePath() const { - Q_ASSERT(has_metadata()); - QString fsave_path = fsutils::fromNativePath(TorrentPersistentData::getSavePath(hash())); - if (fsave_path.isEmpty()) - fsave_path = save_path(); - if (!fsave_path.endsWith("/")) - fsave_path += "/"; - fsave_path += filepath_at(0); - // Remove .!qB extension - if (fsave_path.endsWith(".!qB", Qt::CaseInsensitive)) - fsave_path.chop(4); - return fsave_path; +QString QTorrentHandle::firstFileSavePath() const +{ + Q_ASSERT(has_metadata()); + QString fsave_path = fsutils::fromNativePath(TorrentPersistentData::getSavePath(hash())); + if (fsave_path.isEmpty()) + fsave_path = save_path(); + if (!fsave_path.endsWith("/")) + fsave_path += "/"; + fsave_path += filepath_at(0); + // Remove .!qB extension + if (fsave_path.endsWith(".!qB", Qt::CaseInsensitive)) + fsave_path.chop(4); + return fsave_path; } QString QTorrentHandle::root_path() const { - if (num_files() < 2) + if (num_files() < 2) + return save_path(); + QString first_filepath = filepath_at(0); + const int slashIndex = first_filepath.indexOf("/"); + if (slashIndex >= 0) + return QDir(save_path()).absoluteFilePath(first_filepath.left(slashIndex)); return save_path(); - QString first_filepath = filepath_at(0); - const int slashIndex = first_filepath.indexOf("/"); - if (slashIndex >= 0) - return QDir(save_path()).absoluteFilePath(first_filepath.left(slashIndex)); - return save_path(); } -bool QTorrentHandle::has_error() const { - return has_error(status(0x0)); +bool QTorrentHandle::has_error() const +{ + return has_error(status(0x0)); } -QString QTorrentHandle::error() const { - return misc::toQString(status(0x0).error); +QString QTorrentHandle::error() const +{ + return misc::toQString(status(0x0).error); } -void QTorrentHandle::downloading_pieces(bitfield &bf) const { - std::vector queue; - torrent_handle::get_download_queue(queue); +void QTorrentHandle::downloading_pieces(bitfield &bf) const +{ + std::vector queue; + torrent_handle::get_download_queue(queue); - std::vector::const_iterator it = queue.begin(); - std::vector::const_iterator itend = queue.end(); - for ( ; it!= itend; ++it) { - bf.set_bit(it->piece_index); - } - return; + std::vector::const_iterator it = queue.begin(); + std::vector::const_iterator itend = queue.end(); + for (; it!= itend; ++it) + bf.set_bit(it->piece_index); + return; } -bool QTorrentHandle::has_metadata() const { - return status(0x0).has_metadata; +bool QTorrentHandle::has_metadata() const +{ + return status(0x0).has_metadata; } -void QTorrentHandle::file_progress(std::vector& fp) const { +void QTorrentHandle::file_progress(std::vector& fp) const +{ torrent_handle::file_progress(fp, torrent_handle::piece_granularity); } -QTorrentState QTorrentHandle::torrentState() const { +QTorrentState QTorrentHandle::torrentState() const +{ QTorrentState state = QTorrentState::Unknown; libtorrent::torrent_status s = status(torrent_handle::query_accurate_download_counters); @@ -456,275 +493,295 @@ qulonglong QTorrentHandle::eta() const // Setters // -void QTorrentHandle::pause() const { - torrent_handle::auto_managed(false); - torrent_handle::pause(); - torrent_handle::save_resume_data(); +void QTorrentHandle::pause() const +{ + torrent_handle::auto_managed(false); + torrent_handle::pause(); + torrent_handle::save_resume_data(); } -void QTorrentHandle::resume() const { - if (has_error()) - torrent_handle::clear_error(); +void QTorrentHandle::resume() const +{ + if (has_error()) + torrent_handle::clear_error(); - const QString torrent_hash = hash(); - bool has_persistant_error = TorrentPersistentData::hasError(torrent_hash); - TorrentPersistentData::setErrorState(torrent_hash, false); - bool temp_path_enabled = Preferences::instance()->isTempPathEnabled(); - if (has_persistant_error && temp_path_enabled) { - // Torrent was supposed to be seeding, checking again in final destination - qDebug("Resuming a torrent with error..."); - const QString final_save_path = TorrentPersistentData::getSavePath(torrent_hash); - qDebug("Torrent final path is: %s", qPrintable(final_save_path)); - if (!final_save_path.isEmpty()) - move_storage(final_save_path); - } - torrent_handle::auto_managed(true); - torrent_handle::resume(); - if (has_persistant_error && temp_path_enabled) { - // Force recheck - torrent_handle::force_recheck(); - } + const QString torrent_hash = hash(); + bool has_persistant_error = TorrentPersistentData::hasError(torrent_hash); + TorrentPersistentData::setErrorState(torrent_hash, false); + bool temp_path_enabled = Preferences::instance()->isTempPathEnabled(); + if (has_persistant_error && temp_path_enabled) { + // Torrent was supposed to be seeding, checking again in final destination + qDebug("Resuming a torrent with error..."); + const QString final_save_path = TorrentPersistentData::getSavePath(torrent_hash); + qDebug("Torrent final path is: %s", qPrintable(final_save_path)); + if (!final_save_path.isEmpty()) + move_storage(final_save_path); + } + torrent_handle::auto_managed(true); + torrent_handle::resume(); + if (has_persistant_error && temp_path_enabled) + // Force recheck + torrent_handle::force_recheck(); } -void QTorrentHandle::remove_url_seed(const QString& seed) const { - torrent_handle::remove_url_seed(seed.toStdString()); +void QTorrentHandle::remove_url_seed(const QString& seed) const +{ + torrent_handle::remove_url_seed(seed.toStdString()); } -void QTorrentHandle::add_url_seed(const QString& seed) const { - const std::string str_seed = seed.toStdString(); - qDebug("calling torrent_handle::add_url_seed(%s)", str_seed.c_str()); - torrent_handle::add_url_seed(str_seed); +void QTorrentHandle::add_url_seed(const QString& seed) const +{ + const std::string str_seed = seed.toStdString(); + qDebug("calling torrent_handle::add_url_seed(%s)", str_seed.c_str()); + torrent_handle::add_url_seed(str_seed); } -void QTorrentHandle::set_tracker_login(const QString& username, const QString& password) const { - torrent_handle::set_tracker_login(std::string(username.toLocal8Bit().constData()), std::string(password.toLocal8Bit().constData())); +void QTorrentHandle::set_tracker_login(const QString& username, const QString& password) const +{ + torrent_handle::set_tracker_login(std::string(username.toLocal8Bit().constData()), std::string(password.toLocal8Bit().constData())); } -void QTorrentHandle::move_storage(const QString& new_path) const { - QString hashstr = hash(); +void QTorrentHandle::move_storage(const QString& new_path) const +{ + QString hashstr = hash(); - if (TorrentTempData::isMoveInProgress(hashstr)) { - qDebug("enqueue move storage to %s", qPrintable(new_path)); - TorrentTempData::enqueueMove(hashstr, new_path); - } - else { - QString old_path = save_path(); + if (TorrentTempData::isMoveInProgress(hashstr)) { + qDebug("enqueue move storage to %s", qPrintable(new_path)); + TorrentTempData::enqueueMove(hashstr, new_path); + } + else { + QString old_path = save_path(); - qDebug("move storage: %s to %s", qPrintable(old_path), qPrintable(new_path)); + qDebug("move storage: %s to %s", qPrintable(old_path), qPrintable(new_path)); - if (QDir(old_path) == QDir(new_path)) - return; + if (QDir(old_path) == QDir(new_path)) + return; - TorrentTempData::startMove(hashstr, old_path, new_path); + TorrentTempData::startMove(hashstr, old_path, new_path); - // Create destination directory if necessary - // or move_storage() will fail... - QDir().mkpath(new_path); - // Actually move the storage - torrent_handle::move_storage(fsutils::toNativePath(new_path).toUtf8().constData()); - } + // Create destination directory if necessary + // or move_storage() will fail... + QDir().mkpath(new_path); + // Actually move the storage + torrent_handle::move_storage(fsutils::toNativePath(new_path).toUtf8().constData()); + } } -bool QTorrentHandle::save_torrent_file(const QString& path) const { - if (!has_metadata()) return false; +bool QTorrentHandle::save_torrent_file(const QString& path) const +{ + if (!has_metadata()) return false; #if LIBTORRENT_VERSION_NUM < 10000 - torrent_info const* t = &get_torrent_info(); + torrent_info const* t = &get_torrent_info(); #else - boost::intrusive_ptr t = torrent_file(); + boost::intrusive_ptr t = torrent_file(); #endif - entry meta = bdecode(t->metadata().get(), - t->metadata().get() + t->metadata_size()); - entry torrent_entry(entry::dictionary_t); - torrent_entry["info"] = meta; - if (!torrent_handle::trackers().empty()) - torrent_entry["announce"] = torrent_handle::trackers().front().url; + entry meta = bdecode(t->metadata().get(), + t->metadata().get() + t->metadata_size()); + entry torrent_entry(entry::dictionary_t); + torrent_entry["info"] = meta; + if (!torrent_handle::trackers().empty()) + torrent_entry["announce"] = torrent_handle::trackers().front().url; - vector out; - bencode(back_inserter(out), torrent_entry); - QFile torrent_file(path); - if (!out.empty() && torrent_file.open(QIODevice::WriteOnly)) { - torrent_file.write(&out[0], out.size()); - torrent_file.close(); - return true; - } + vector out; + bencode(back_inserter(out), torrent_entry); + QFile torrent_file(path); + if (!out.empty() && torrent_file.open(QIODevice::WriteOnly)) { + torrent_file.write(&out[0], out.size()); + torrent_file.close(); + return true; + } - return false; + return false; } -void QTorrentHandle::file_priority(int index, int priority) const { - vector priorities = torrent_handle::file_priorities(); - if (priorities[index] != priority) { - priorities[index] = priority; - prioritize_files(priorities); - } +void QTorrentHandle::file_priority(int index, int priority) const +{ + vector priorities = torrent_handle::file_priorities(); + if (priorities[index] != priority) { + priorities[index] = priority; + prioritize_files(priorities); + } } -void QTorrentHandle::prioritize_files(const vector &files) const { +void QTorrentHandle::prioritize_files(const vector &files) const +{ #if LIBTORRENT_VERSION_NUM < 10000 - torrent_info const& info = torrent_handle::get_torrent_info(); + torrent_info const& info = torrent_handle::get_torrent_info(); #else - boost::intrusive_ptr info_ptr = torrent_handle::torrent_file(); - torrent_info const& info = *info_ptr; + boost::intrusive_ptr info_ptr = torrent_handle::torrent_file(); + torrent_info const& info = *info_ptr; #endif - if ((int)files.size() != info.num_files()) return; - qDebug() << Q_FUNC_INFO; - bool was_seed = is_seed(); - qDebug() << Q_FUNC_INFO << "Changing files priorities..."; - torrent_handle::prioritize_files(files); - qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely..."; + if ((int)files.size() != info.num_files()) return; + qDebug() << Q_FUNC_INFO; + bool was_seed = is_seed(); + qDebug() << Q_FUNC_INFO << "Changing files priorities..."; + torrent_handle::prioritize_files(files); + qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely..."; - QString spath = save_path(); + QString spath = save_path(); - for (uint i = 0; i < files.size(); ++i) { - QString filepath = filepath_at(info, i); - // Move unwanted files to a .unwanted subfolder - if (files[i] == 0) { - QString old_abspath = QDir(spath).absoluteFilePath(filepath); - QString parent_abspath = fsutils::branchPath(old_abspath); - // Make sure the file does not already exists - if (QDir(parent_abspath).dirName() != ".unwanted") { - QString unwanted_abspath = parent_abspath+"/.unwanted"; - QString new_abspath = unwanted_abspath+"/"+fsutils::fileName(filepath); - qDebug() << "Unwanted path is" << unwanted_abspath; - if (QFile::exists(new_abspath)) { - qWarning() << "File" << new_abspath << "already exists at destination."; - continue; - } - bool created = QDir().mkpath(unwanted_abspath); + for (uint i = 0; i < files.size(); ++i) { + QString filepath = filepath_at(info, i); + // Move unwanted files to a .unwanted subfolder + if (files[i] == 0) { + QString old_abspath = QDir(spath).absoluteFilePath(filepath); + QString parent_abspath = fsutils::branchPath(old_abspath); + // Make sure the file does not already exists + if (QDir(parent_abspath).dirName() != ".unwanted") { + QString unwanted_abspath = parent_abspath + "/.unwanted"; + QString new_abspath = unwanted_abspath + "/" + fsutils::fileName(filepath); + qDebug() << "Unwanted path is" << unwanted_abspath; + if (QFile::exists(new_abspath)) { + qWarning() << "File" << new_abspath << "already exists at destination."; + continue; + } + bool created = QDir().mkpath(unwanted_abspath); #ifdef Q_OS_WIN - qDebug() << "unwanted folder was created:" << created; - if (created) { - // Hide the folder on Windows - qDebug() << "Hiding folder (Windows)"; - wstring win_path = fsutils::toNativePath(unwanted_abspath).toStdWString(); - DWORD dwAttrs = GetFileAttributesW(win_path.c_str()); - bool ret = SetFileAttributesW(win_path.c_str(), dwAttrs|FILE_ATTRIBUTE_HIDDEN); - Q_ASSERT(ret != 0); Q_UNUSED(ret); - } + qDebug() << "unwanted folder was created:" << created; + if (created) { + // Hide the folder on Windows + qDebug() << "Hiding folder (Windows)"; + wstring win_path = fsutils::toNativePath(unwanted_abspath).toStdWString(); + DWORD dwAttrs = GetFileAttributesW(win_path.c_str()); + bool ret = SetFileAttributesW(win_path.c_str(), dwAttrs | FILE_ATTRIBUTE_HIDDEN); + Q_ASSERT(ret != 0); Q_UNUSED(ret); + } #else - Q_UNUSED(created); + Q_UNUSED(created); #endif - QString parent_path = fsutils::branchPath(filepath); - if (!parent_path.isEmpty() && !parent_path.endsWith("/")) - parent_path += "/"; - rename_file(i, parent_path+".unwanted/"+fsutils::fileName(filepath)); - } + QString parent_path = fsutils::branchPath(filepath); + if (!parent_path.isEmpty() && !parent_path.endsWith("/")) + parent_path += "/"; + rename_file(i, parent_path + ".unwanted/" + fsutils::fileName(filepath)); + } + } + // Move wanted files back to their original folder + if (files[i] > 0) { + QString parent_relpath = fsutils::branchPath(filepath); + if (QDir(parent_relpath).dirName() == ".unwanted") { + QString old_name = fsutils::fileName(filepath); + QString new_relpath = fsutils::branchPath(parent_relpath); + if (new_relpath.isEmpty()) + rename_file(i, old_name); + else + rename_file(i, QDir(new_relpath).filePath(old_name)); + // Remove .unwanted directory if empty + qDebug() << "Attempting to remove .unwanted folder at " << QDir(spath + "/" + new_relpath).absoluteFilePath(".unwanted"); + QDir(spath + "/" + new_relpath).rmdir(".unwanted"); + } + } } - // Move wanted files back to their original folder - if (files[i] > 0) { - QString parent_relpath = fsutils::branchPath(filepath); - if (QDir(parent_relpath).dirName() == ".unwanted") { - QString old_name = fsutils::fileName(filepath); - QString new_relpath = fsutils::branchPath(parent_relpath); - if (new_relpath.isEmpty()) - rename_file(i, old_name); - else - rename_file(i, QDir(new_relpath).filePath(old_name)); - // Remove .unwanted directory if empty - qDebug() << "Attempting to remove .unwanted folder at " << QDir(spath + "/" + new_relpath).absoluteFilePath(".unwanted"); - QDir(spath + "/" + new_relpath).rmdir(".unwanted"); - } - } - } - if (was_seed && !is_seed()) { - qDebug() << "Torrent is no longer SEEDING"; - // Save seed status - TorrentPersistentData::saveSeedStatus(*this); - // Move to temp folder if necessary - const Preferences* const pref = Preferences::instance(); - if (pref->isTempPathEnabled()) { - QString tmp_path = pref->getTempPath(); - qDebug() << "tmp folder is enabled, move torrent to " << tmp_path << " from " << spath; - move_storage(tmp_path); + if (was_seed && !is_seed()) { + qDebug() << "Torrent is no longer SEEDING"; + // Save seed status + TorrentPersistentData::saveSeedStatus(*this); + // Move to temp folder if necessary + const Preferences* const pref = Preferences::instance(); + if (pref->isTempPathEnabled()) { + QString tmp_path = pref->getTempPath(); + qDebug() << "tmp folder is enabled, move torrent to " << tmp_path << " from " << spath; + move_storage(tmp_path); + } } - } } -void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const { - // Determine the priority to set - int prio = b ? 7 : torrent_handle::file_priority(file_index); +void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const +{ + // Determine the priority to set + int prio = b ? 7 : torrent_handle::file_priority(file_index); #if LIBTORRENT_VERSION_NUM < 10000 - torrent_info const* tf = &get_torrent_info(); + torrent_info const* tf = &get_torrent_info(); #else - boost::intrusive_ptr tf = torrent_file(); + boost::intrusive_ptr tf = torrent_file(); #endif - QPair extremities = get_file_extremity_pieces(*tf, file_index); - piece_priority(extremities.first, prio); - piece_priority(extremities.second, prio); + QPair extremities = get_file_extremity_pieces(*tf, file_index); + piece_priority(extremities.first, prio); + piece_priority(extremities.second, prio); } -void QTorrentHandle::prioritize_first_last_piece(bool b) const { - if (!has_metadata()) return; - // Download first and last pieces first for all media files in the torrent - const uint nbfiles = num_files(); - for (uint index = 0; index < nbfiles; ++index) { - const QString path = filepath_at(index); - const QString ext = fsutils::fileExtension(path); - if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) { - qDebug() << "File" << path << "is previewable, toggle downloading of first/last pieces first"; - prioritize_first_last_piece(index, b); +void QTorrentHandle::prioritize_first_last_piece(bool b) const +{ + if (!has_metadata()) return; + // Download first and last pieces first for all media files in the torrent + const uint nbfiles = num_files(); + for (uint index = 0; index < nbfiles; ++index) { + const QString path = filepath_at(index); + const QString ext = fsutils::fileExtension(path); + if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) { + qDebug() << "File" << path << "is previewable, toggle downloading of first/last pieces first"; + prioritize_first_last_piece(index, b); + } } - } } -void QTorrentHandle::rename_file(int index, const QString& name) const { - qDebug() << Q_FUNC_INFO << index << name; - torrent_handle::rename_file(index, std::string(fsutils::toNativePath(name).toUtf8().constData())); +void QTorrentHandle::rename_file(int index, const QString& name) const +{ + qDebug() << Q_FUNC_INFO << index << name; + torrent_handle::rename_file(index, std::string(fsutils::toNativePath(name).toUtf8().constData())); } // // Operators // -bool QTorrentHandle::operator ==(const QTorrentHandle& new_h) const { - return info_hash() == new_h.info_hash(); +bool QTorrentHandle::operator ==(const QTorrentHandle& new_h) const +{ + return info_hash() == new_h.info_hash(); } -bool QTorrentHandle::is_paused(const libtorrent::torrent_status &status) { - return status.paused && !status.auto_managed; +bool QTorrentHandle::is_paused(const libtorrent::torrent_status &status) +{ + return status.paused && !status.auto_managed; } -int QTorrentHandle::queue_position(const libtorrent::torrent_status &status) { - if (status.queue_position < 0) - return -1; - return status.queue_position+1; +int QTorrentHandle::queue_position(const libtorrent::torrent_status &status) +{ + if (status.queue_position < 0) + return -1; + return status.queue_position + 1; } -bool QTorrentHandle::is_queued(const libtorrent::torrent_status &status) { - return status.paused && status.auto_managed; +bool QTorrentHandle::is_queued(const libtorrent::torrent_status &status) +{ + return status.paused && status.auto_managed; } -bool QTorrentHandle::is_seed(const libtorrent::torrent_status &status) { - return status.state == torrent_status::finished - || status.state == torrent_status::seeding; +bool QTorrentHandle::is_seed(const libtorrent::torrent_status &status) +{ + return status.state == torrent_status::finished + || status.state == torrent_status::seeding; } -bool QTorrentHandle::is_checking(const libtorrent::torrent_status &status) { - return status.state == torrent_status::checking_files - || status.state == torrent_status::checking_resume_data; +bool QTorrentHandle::is_checking(const libtorrent::torrent_status &status) +{ + return status.state == torrent_status::checking_files + || status.state == torrent_status::checking_resume_data; } -bool QTorrentHandle::has_error(const libtorrent::torrent_status &status) { - return status.paused && !status.error.empty(); +bool QTorrentHandle::has_error(const libtorrent::torrent_status &status) +{ + return status.paused && !status.error.empty(); } -float QTorrentHandle::progress(const libtorrent::torrent_status &status) { - if (!status.total_wanted) - return 0.; - if (status.total_wanted_done == status.total_wanted) - return 1.; - float progress = (float) status.total_wanted_done / (float) status.total_wanted; - Q_ASSERT(progress >= 0.f && progress <= 1.f); - return progress; +float QTorrentHandle::progress(const libtorrent::torrent_status &status) +{ + if (!status.total_wanted) + return 0.; + if (status.total_wanted_done == status.total_wanted) + return 1.; + float progress = (float) status.total_wanted_done / (float) status.total_wanted; + Q_ASSERT(progress >= 0.f && progress <= 1.f); + return progress; } -QString QTorrentHandle::filepath_at(const libtorrent::torrent_info &info, unsigned int index) { - return fsutils::fromNativePath(misc::toQStringU(info.files().file_path(index))); +QString QTorrentHandle::filepath_at(const libtorrent::torrent_info &info, unsigned int index) +{ + return fsutils::fromNativePath(misc::toQStringU(info.files().file_path(index))); } diff --git a/src/qtlibtorrent/qtorrenthandle.h b/src/qtlibtorrent/qtorrenthandle.h index 6c25dcc96..a36593ba5 100644 --- a/src/qtlibtorrent/qtorrenthandle.h +++ b/src/qtlibtorrent/qtorrenthandle.h @@ -42,7 +42,8 @@ QT_END_NAMESPACE class QTorrentState { public: - enum { + enum + { Unknown = -1, Error, @@ -71,93 +72,94 @@ private: // A wrapper for torrent_handle in libtorrent // to interact well with Qt types -class QTorrentHandle : public libtorrent::torrent_handle { +class QTorrentHandle: public libtorrent::torrent_handle +{ public: - // - // Constructors - // + // + // Constructors + // - QTorrentHandle() {} - explicit QTorrentHandle(const libtorrent::torrent_handle& h); + QTorrentHandle() {} + explicit QTorrentHandle(const libtorrent::torrent_handle& h); - // - // Getters - // - QString hash() const; - QString name() const; - QString current_tracker() const; - bool is_paused() const; - bool has_filtered_pieces() const; - libtorrent::size_type total_size() const; - libtorrent::size_type piece_length() const; - int num_pieces() const; - QString save_path() const; - QString save_path_parsed() const; - QStringList url_seeds() const; - libtorrent::size_type actual_size() const; - int num_files() const; - int queue_position() const; - bool is_queued() const; - QString filename_at(unsigned int index) const; - libtorrent::size_type filesize_at(unsigned int index) const; - QString filepath_at(unsigned int index) const; - QString orig_filepath_at(unsigned int index) const; - libtorrent::torrent_status::state_t state() const; - QString creator() const; - QString comment() const; - QStringList absolute_files_path() const; - QStringList absolute_files_path_uneeded() const; - bool has_missing_files() const; - bool is_seed() const; - bool is_checking() const; - bool is_sequential_download() const; - QString creation_date() const; - qlonglong creation_date_unix() const; - bool priv() const; - bool first_last_piece_first() const; - QString root_path() const; - QString firstFileSavePath() const; - bool has_error() const; - QString error() const; - void downloading_pieces(libtorrent::bitfield& bf) const; - bool has_metadata() const; - void file_progress(std::vector& fp) const; - QTorrentState torrentState() const; - qulonglong eta() const; + // + // Getters + // + QString hash() const; + QString name() const; + QString current_tracker() const; + bool is_paused() const; + bool has_filtered_pieces() const; + libtorrent::size_type total_size() const; + libtorrent::size_type piece_length() const; + int num_pieces() const; + QString save_path() const; + QString save_path_parsed() const; + QStringList url_seeds() const; + libtorrent::size_type actual_size() const; + int num_files() const; + int queue_position() const; + bool is_queued() const; + QString filename_at(unsigned int index) const; + libtorrent::size_type filesize_at(unsigned int index) const; + QString filepath_at(unsigned int index) const; + QString orig_filepath_at(unsigned int index) const; + libtorrent::torrent_status::state_t state() const; + QString creator() const; + QString comment() const; + QStringList absolute_files_path() const; + QStringList absolute_files_path_uneeded() const; + bool has_missing_files() const; + bool is_seed() const; + bool is_checking() const; + bool is_sequential_download() const; + QString creation_date() const; + qlonglong creation_date_unix() const; + bool priv() const; + bool first_last_piece_first() const; + QString root_path() const; + QString firstFileSavePath() const; + bool has_error() const; + QString error() const; + void downloading_pieces(libtorrent::bitfield& bf) const; + bool has_metadata() const; + void file_progress(std::vector& fp) const; + QTorrentState torrentState() const; + qulonglong eta() const; - // - // Setters - // - void pause() const; - void resume() const; - void remove_url_seed(const QString& seed) const; - void add_url_seed(const QString& seed) const; - void set_tracker_login(const QString& username, const QString& password) const; - void move_storage(const QString& path) const; - void prioritize_first_last_piece(bool b) const; - void rename_file(int index, const QString& name) const; - bool save_torrent_file(const QString& path) const; - void prioritize_files(const std::vector& files) const; - void file_priority(int index, int priority) const; + // + // Setters + // + void pause() const; + void resume() const; + void remove_url_seed(const QString& seed) const; + void add_url_seed(const QString& seed) const; + void set_tracker_login(const QString& username, const QString& password) const; + void move_storage(const QString& path) const; + void prioritize_first_last_piece(bool b) const; + void rename_file(int index, const QString& name) const; + bool save_torrent_file(const QString& path) const; + void prioritize_files(const std::vector& files) const; + void file_priority(int index, int priority) const; - // - // Operators - // - bool operator ==(const QTorrentHandle& new_h) const; + // + // Operators + // + bool operator ==(const QTorrentHandle& new_h) const; - static bool is_paused(const libtorrent::torrent_status &status); - static int queue_position(const libtorrent::torrent_status &status); - static bool is_queued(const libtorrent::torrent_status &status); - static bool is_seed(const libtorrent::torrent_status &status); - static bool is_checking(const libtorrent::torrent_status &status); - static bool has_error(const libtorrent::torrent_status &status); - static float progress(const libtorrent::torrent_status &status); - static QString filepath_at(const libtorrent::torrent_info &info, unsigned int index); + static bool is_paused(const libtorrent::torrent_status &status); + static int queue_position(const libtorrent::torrent_status &status); + static bool is_queued(const libtorrent::torrent_status &status); + static bool is_seed(const libtorrent::torrent_status &status); + static bool is_checking(const libtorrent::torrent_status &status); + static bool has_error(const libtorrent::torrent_status &status); + static float progress(const libtorrent::torrent_status &status); + static QString filepath_at(const libtorrent::torrent_info &info, unsigned int index); private: - void prioritize_first_last_piece(int file_index, bool b) const; + void prioritize_first_last_piece(int file_index, bool b) const; }; diff --git a/src/transferlistwidget.cpp b/src/transferlistwidget.cpp index 2b9a09614..382e76359 100644 --- a/src/transferlistwidget.cpp +++ b/src/transferlistwidget.cpp @@ -68,858 +68,884 @@ using namespace libtorrent; TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window, QBtSession *_BTSession): - QTreeView(parent), BTSession(_BTSession), main_window(main_window) { + QTreeView(parent), BTSession(_BTSession), main_window(main_window) +{ - setUniformRowHeights(true); - // Load settings - bool column_loaded = loadSettings(); + setUniformRowHeights(true); + // Load settings + bool column_loaded = loadSettings(); - // Create and apply delegate - listDelegate = new TransferListDelegate(this); - setItemDelegate(listDelegate); + // Create and apply delegate + listDelegate = new TransferListDelegate(this); + setItemDelegate(listDelegate); - // Create transfer list model - listModel = new TorrentModel(this); + // Create transfer list model + listModel = new TorrentModel(this); - nameFilterModel = new TransferListSortModel(); - nameFilterModel->setDynamicSortFilter(true); - nameFilterModel->setSourceModel(listModel); - nameFilterModel->setFilterKeyColumn(TorrentModelItem::TR_NAME); - nameFilterModel->setFilterRole(Qt::DisplayRole); - nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive); + nameFilterModel = new TransferListSortModel(); + nameFilterModel->setDynamicSortFilter(true); + nameFilterModel->setSourceModel(listModel); + nameFilterModel->setFilterKeyColumn(TorrentModelItem::TR_NAME); + nameFilterModel->setFilterRole(Qt::DisplayRole); + nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive); - setModel(nameFilterModel); + setModel(nameFilterModel); - // Visual settings - setRootIsDecorated(false); - setAllColumnsShowFocus(true); - setSortingEnabled(true); - setSelectionMode(QAbstractItemView::ExtendedSelection); - setItemsExpandable(false); - setAutoScroll(true); - setDragDropMode(QAbstractItemView::DragOnly); + // Visual settings + setRootIsDecorated(false); + setAllColumnsShowFocus(true); + setSortingEnabled(true); + setSelectionMode(QAbstractItemView::ExtendedSelection); + setItemsExpandable(false); + setAutoScroll(true); + setDragDropMode(QAbstractItemView::DragOnly); #if defined(Q_OS_MAC) - setAttribute(Qt::WA_MacShowFocusRect, false); + setAttribute(Qt::WA_MacShowFocusRect, false); #endif - header()->setStretchLastSection(false); + header()->setStretchLastSection(false); - // Default hidden columns - if (!column_loaded) { - setColumnHidden(TorrentModelItem::TR_PRIORITY, true); - setColumnHidden(TorrentModelItem::TR_ADD_DATE, true); - setColumnHidden(TorrentModelItem::TR_SEED_DATE, true); - setColumnHidden(TorrentModelItem::TR_UPLIMIT, true); - setColumnHidden(TorrentModelItem::TR_DLLIMIT, true); - setColumnHidden(TorrentModelItem::TR_TRACKER, true); - setColumnHidden(TorrentModelItem::TR_AMOUNT_DOWNLOADED, true); - setColumnHidden(TorrentModelItem::TR_AMOUNT_UPLOADED, true); - setColumnHidden(TorrentModelItem::TR_AMOUNT_LEFT, true); - setColumnHidden(TorrentModelItem::TR_TIME_ELAPSED, true); - setColumnHidden(TorrentModelItem::TR_SAVE_PATH, true); - setColumnHidden(TorrentModelItem::TR_COMPLETED, true); - setColumnHidden(TorrentModelItem::TR_RATIO_LIMIT, true); - setColumnHidden(TorrentModelItem::TR_SEEN_COMPLETE_DATE, true); - setColumnHidden(TorrentModelItem::TR_LAST_ACTIVITY, true); - setColumnHidden(TorrentModelItem::TR_TOTAL_SIZE, true); - } - - //Ensure that at least one column is visible at all times - bool atLeastOne = false; - for (unsigned int i=0; i