diff --git a/extras/rpc-spec.txt b/extras/rpc-spec.txt index 9b9c3eb1b..cc732f05b 100644 --- a/extras/rpc-spec.txt +++ b/extras/rpc-spec.txt @@ -190,6 +190,7 @@ downloadedEver | number | tr_stat downloadLimit | number | tr_torrent downloadLimited | boolean | tr_torrent + editDate | number | tr_stat error | number | tr_stat errorString | string | tr_stat eta | number | tr_stat @@ -806,6 +807,7 @@ | | yes | session-get | new arg "session-id" | | yes | torrent-get | new arg "labels" | | yes | torrent-set | new arg "labels" + | | yes | torrent-set | new arg "editDate" | | yes | torrent-get | new arg "format" diff --git a/libtransmission/quark.c b/libtransmission/quark.c index 3bcedb2c7..1a7042452 100644 --- a/libtransmission/quark.c +++ b/libtransmission/quark.c @@ -105,6 +105,7 @@ static struct tr_key_struct const my_static[] = Q("dropped"), Q("dropped6"), Q("e"), + Q("editDate"), Q("encoding"), Q("encryption"), Q("error"), diff --git a/libtransmission/quark.h b/libtransmission/quark.h index 87aad80f6..553df3a1c 100644 --- a/libtransmission/quark.h +++ b/libtransmission/quark.h @@ -105,6 +105,7 @@ enum TR_KEY_dropped, TR_KEY_dropped6, TR_KEY_e, + TR_KEY_editDate, TR_KEY_encoding, TR_KEY_encryption, TR_KEY_error, diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c index fc0bc72ad..272a1c469 100644 --- a/libtransmission/rpcimpl.c +++ b/libtransmission/rpcimpl.c @@ -641,6 +641,10 @@ static void initField(tr_torrent* const tor, tr_info const* const inf, tr_stat c tr_variantInitInt(initme, st->id); break; + case TR_KEY_editDate: + tr_variantInitInt(initme, st->editDate); + break; + case TR_KEY_isFinished: tr_variantInitBool(initme, st->finished); break; diff --git a/libtransmission/torrent-magnet.c b/libtransmission/torrent-magnet.c index 544b09cbe..33e820f26 100644 --- a/libtransmission/torrent-magnet.c +++ b/libtransmission/torrent-magnet.c @@ -340,6 +340,7 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, in tor->isStopping = true; tor->magnetVerify = true; tor->startAfterVerify = true; + tr_torrentMarkEdited(tor); } else /* drat. */ { diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index 4bc631e77..330358865 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -1191,6 +1191,8 @@ void tr_torrentSetDownloadDir(tr_torrent* tor, char const* path) { tr_free(tor->downloadDir); tor->downloadDir = tr_strdup(path); + + tr_torrentMarkEdited(tor); tr_torrentSetDirty(tor); } @@ -1406,6 +1408,7 @@ tr_stat const* tr_torrentStat(tr_torrent* tor) s->activityDate = tor->activityDate; s->addedDate = tor->addedDate; s->doneDate = tor->doneDate; + s->editDate = tor->editDate; s->startDate = tor->startDate; s->secondsSeeding = tor->secondsSeeding; s->secondsDownloading = tor->secondsDownloading; @@ -2862,6 +2865,7 @@ bool tr_torrentSetAnnounceList(tr_torrent* tor, tr_tracker_info const* trackers_ tor->info.trackerCount = tmpInfo.trackerCount; tmpInfo.trackers = swap.trackers; tmpInfo.trackerCount = swap.trackerCount; + tr_torrentMarkEdited(tor); tr_metainfoFree(&tmpInfo); tr_variantToFile(&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent); @@ -4005,6 +4009,7 @@ static void torrentRenamePath(void* vdata) tor->info.name = tr_strdup(newname); } + tr_torrentMarkEdited(tor); tr_torrentSetDirty(tor); } } diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 9898c6f07..e0c9aca3b 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -191,11 +191,12 @@ struct tr_torrent uint64_t etaULSpeedCalculatedAt; unsigned int etaULSpeed_Bps; - time_t addedDate; time_t activityDate; - time_t doneDate; - time_t startDate; + time_t addedDate; time_t anyDate; + time_t doneDate; + time_t editDate; + time_t startDate; int secondsDownloading; int secondsSeeding; @@ -349,6 +350,14 @@ static inline void tr_torrentSetDirty(tr_torrent* tor) tor->isDirty = true; } +/* note that the torrent's tr_info just changed */ +static inline void tr_torrentMarkEdited(tr_torrent* tor) +{ + TR_ASSERT(tr_isTorrent(tor)); + + tor->editDate = tr_time(); +} + uint32_t tr_getBlockSize(uint32_t pieceSize); /** diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index f0136c849..33e880c0f 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -1828,6 +1828,12 @@ typedef struct tr_stat /** The last time we uploaded or downloaded piece data on this torrent. */ time_t activityDate; + /** The last time during this session that a rarely-changing field + changed -- e.g. any tr_info field (trackers, filenames, name) + or download directory. RPC clients can monitor this to know when + to reload fields that rarely change. */ + time_t editDate; + /** Number of seconds since the last activity (or since started). -1 if activity is not seeding or downloading. */ int idleSecs; diff --git a/qt/Application.cc b/qt/Application.cc index 6e2867239..685453e4f 100644 --- a/qt/Application.cc +++ b/qt/Application.cc @@ -399,6 +399,12 @@ void Application::quitLater() QTimer::singleShot(0, this, SLOT(quit())); } +void Application::onTorrentsEdited(torrent_ids_t const& ids) +{ + // the backend's tr_info has changed, so reload those fields + mySession->initTorrents(ids); +} + QStringList Application::getNames(torrent_ids_t const& ids) const { QStringList names; diff --git a/qt/Application.h b/qt/Application.h index dec2d7386..953303e4a 100644 --- a/qt/Application.h +++ b/qt/Application.h @@ -18,6 +18,7 @@ class AddData; class Prefs; class Session; +class Torrent; class TorrentModel; class MainWindow; class WatchDir; @@ -41,11 +42,12 @@ public slots: private slots: void consentGiven(int result); void onSessionSourceChanged(); - void refreshPref(int key); - void refreshTorrents(); void onTorrentsAdded(torrent_ids_t const& torrents); void onTorrentsCompleted(torrent_ids_t const& torrents); + void onTorrentsEdited(torrent_ids_t const& torrents); void onTorrentsNeedInfo(torrent_ids_t const& torrents); + void refreshPref(int key); + void refreshTorrents(); private: void maybeUpdateBlocklist(); diff --git a/qt/DetailsDialog.cc b/qt/DetailsDialog.cc index 4afde07ff..5b7810879 100644 --- a/qt/DetailsDialog.cc +++ b/qt/DetailsDialog.cc @@ -310,6 +310,12 @@ void DetailsDialog::getNewData() } } +void DetailsDialog::onTorrentEdited(torrent_ids_t const& /*ids*/) +{ + // FIXME + // refreshDetailInfo({ tor.id() }); +} + void DetailsDialog::onTorrentsChanged(torrent_ids_t const& ids) { if (myHavePendingRefresh) diff --git a/qt/DetailsDialog.h b/qt/DetailsDialog.h index ebb117851..061160fc6 100644 --- a/qt/DetailsDialog.h +++ b/qt/DetailsDialog.h @@ -59,10 +59,11 @@ private: private slots: void refresh(); void refreshPref(int key); - - void onTorrentsChanged(torrent_ids_t const& ids); void onTimer(); + void onTorrentEdited(torrent_ids_t const& ids); + void onTorrentsChanged(torrent_ids_t const& ids); + // Tracker tab void onTrackerSelectionChanged(); void onAddTrackerClicked(); diff --git a/qt/Torrent.cc b/qt/Torrent.cc index 5c0479c01..799749f0b 100644 --- a/qt/Torrent.cc +++ b/qt/Torrent.cc @@ -646,10 +646,16 @@ bool Torrent::update(tr_quark const* keys, tr_variant** values, size_t n) case QVariant::DateTime: { int64_t val; - - if (tr_variantGetInt(child, &val) && val) + if (tr_variantGetInt(child, &val) && val && + setTime(property_index, time_t(val))) { - changed |= setTime(property_index, time_t(val)); + changed = true; + + if (key == TR_KEY_editDate) + { + // FIXME + // emit torrentEdited(*this); + } } break; diff --git a/qt/Torrent.h b/qt/Torrent.h index 77bee9db5..08cdaa2e4 100644 --- a/qt/Torrent.h +++ b/qt/Torrent.h @@ -180,6 +180,7 @@ public: PEERS, BANDWIDTH_PRIORITY, QUEUE_POSITION, + EDIT_DATE, // PROPERTY_COUNT }; diff --git a/qt/TorrentModel.h b/qt/TorrentModel.h index 3df7066fa..1a4c57e02 100644 --- a/qt/TorrentModel.h +++ b/qt/TorrentModel.h @@ -59,6 +59,7 @@ signals: void torrentsAdded(torrent_ids_t const&); void torrentsChanged(torrent_ids_t const&); void torrentsCompleted(torrent_ids_t const&); + void torrentsEdited(torrent_ids_t const&); void torrentsNeedInfo(torrent_ids_t const&); private: