/** The way this will work (preliminary): ------------------------------------ o A unique download is identified by a User-File pair. o A unique GDL (group of downloads) is indentified by a File and GDL ID. o A download is always stored as a unique source inside a GDL item. o A GDL item can contain multiple downloads: same file name, but different users. o Active downloads are stored inside the GDL in the active_gdls list, while downloads that are queued are stored inside the GDL item in queued_gdls list. o If a GDL has any active downloads, then a static copy of the same GDL also exists in the active_gdls list. The copy has same File and ID, but unlike the original, it is required to contain at least one download (active). If the last active download stops, the GDL copy is destroyed. o A GDL whose File isn't fully downloaded remains in the queued_gdls list. GDLs in the queued_gdls list do not have to contain any sources. o A GDL in queued_gdls is destroyed only when it's File is completely downloaded. The completed File's name is then added to the download history. o If an inactive download becomes active, it is moved into the corresponding GDL in active_gdls list. If no such GDL exists, it's created. o If a download finishes, but the GDL still has other downloads running, the download is destroyed. o If an active download is aborted abnormally, it is moved back to the master GDL in the queued_gdls list. o If you haven't slept for 36+ hours, you begin to automatically drool */ #ifndef _GDL_TRANSFER_WIDGET_H_ #define _GDL_TRANSFER_WIDGET_H_ #include #include #include #include #include #include #include "transfer_storage.h" using namespace std; class transfer_widget : public QWidget { Q_OBJECT protected: enum T_TABS {T_DL=0, T_Q, T_UL, T_H, T_MAX}; enum PM_IDS {PM_CloseGDL=1, PM_CloseAllGDL, PM_ActivateGDL, PM_ActivateAllGDL, PM_DeleteGDL, PM_DeleteAllGDL, PM_SetTgtDir, PM_CloseDL, PM_CloseUL, PM_ClearHistory, PM_GetFileList}; // Start dl/gdl signals are not emitted at once, but put in a queue. // A timer-based function pops queued signals and emits them one at // a time. This struct is what we use to store signal data in. enum QS_IDS { QS_NOID=0, QS_NEWGDL, QS_NEWSRC, QS_ATTACH, QS_DETACH }; struct queued_signal { QS_IDS type; unsigned int id; QString user; QString remote_file; QString local_file; ULLINT size; }; // Queue of new gdl/dl signals. list dl_signal_queue; // Timer for emitting signal Start GLD / Add GDL source QTimer *signal_emit_timer; // GDL-update timestamp long gdlinfo_timestamp; // GDL-update-request signal timer QTimer *gdlup_timer; bool is_updating; // Store GDLs (queued & active) and uploads in maps typedef QMap UploadsMap; typedef QMap GDLsMap; typedef QMap NameMap; UploadsMap ul_map; GDLsMap queued_gdls; GDLsMap active_gdls; // when user delets gdl, name and time are stored here NameMap deleted_gdls; // when auto-resuming gdls, name and time are stored here NameMap autoresumed_gdls; // List of download files that may have been completed. DCTC may // need a short time to finish renaming a complete file after it no // longer appears in gdl info list, so we store possibly completed // files here for a while before we check them. NameMap completed_gdl_list; // Download and upload history top-level items QListViewItem *history_dl; QListViewItem *history_ul; // GUI components QTabWidget *tabs; QListView *lv[T_MAX]; QPopupMenu *menu[T_MAX]; QListViewItem *lastClicked[T_MAX]; protected: bool is_user_busy(const QString &uname) const; bool is_gdl_active(const QString &fname) const; void remove_queued_signals(unsigned int); void remove_queued_signals(const QString &name); // Using these methods to queue download start/detach/attach signals. //start new gdl void enqueue_signal(unsigned int id, QString user, QString remote, QString local, ULLINT size); //add src to existing gdl void enqueue_signal(unsigned int id, QString user, QString remote, ULLINT size); //detach by id (need local filename for internal use) void enqueue_signal(unsigned int id, QString local); //attach by filename void enqueue_signal(QString local); void attach_view_items(gdl_item *gdl, const int layout_type); QString update_gdl_in_queue(GDLsMap &gdls, QListView *tgt_lv, const int layout_main_type, const int layout_item_type, const bool erase_outdated, const unsigned int id, const QString &fname, const ULLINT fsize, const ULLINT foffs, const ULLINT frecv, const unsigned int time0, const ULLINT rcv10, const QString &running, const QString &complete); void move_to_history(QListViewItem *h, const QString &file, const QString &user, const ULLINT size); ULLINT process_completed_gdl(gdl_item *gdl); void resume_download(gdl_item *gdl, bool immediately=false); void find_unattached_gdls(); public: transfer_widget( QWidget* parent = 0, const char* name = 0 ); public slots: // saves listview layout void save_layout(); // popup menus void menuClicked(int i); void showMenu(QListViewItem* i, const QPoint &p, int); // update info on a GDL void update_gdl_info(const QString &info); // no more gdl's updated this iteration void update_gdl_end(); // emits "request for gdl info list" signal, avoids multiple unnecessary signals void trigger_gdl_update(); // dequeues and emits a queued download-file signal (either a new gdl or a new dl source) void emit_queued_signal(); // receive info on a new upload void new_ul_info(const QString &info); // update info on an upload void update_ul_info(const QString &info); // update info on an upload void closed_ul_info(const QString &user, const QString &file); // Attaches to a broken download. void restart_download(const QString &fname); // (user, remote_file) identifies a source // (local_file, size) identifies a GDL void download_file(const QString &user, const QString &remote_file, const QString &local_file, unsigned long int fsize); // gdl_id - identifies gdl // user, remote_file, size - identifies new gdl source void new_gdl_source(const unsigned int, const QString &, const QString &, const unsigned long int); // hub_opened() - called when a new hub has been opened & connected to void hub_opened(); signals: void start_gdl(int id, const QString &user, const QString &remote_file, const QString &local_file, unsigned long int size); void add_gdl_source(int id, const QString &user, const QString &remote_file, unsigned long int size); // Attach to a broken/detached GDL in the GDL/ directory. void attach_gdl(const QString &fname); // Detach from a running GDL void detach_gdl(const unsigned int id); // at completion, rename gdl with this id to these fpath/fname void rename_gdl(unsigned int id, const QString &fname, const QString &fpath); void close_gdl(unsigned int id); // GDLEND, total destruction of GDL void close_dl(unsigned int id, const QString &user, const QString &remote_file); // GDLDEL, kills source void close_ul(unsigned int id); // KILL, kill a transfer (we use it for uploads) void request_gdl_update(); void getUserFileList(const QString& user); // status monitor signals void sig_ul_added(); void sig_ul_removed(); void sig_gdl_active(); void sig_gdl_queued(); void sig_gdl_added(const unsigned int, const QString &, const unsigned long); void sig_gdl_removed(const unsigned int id); // preview-dialog signals void sig_gdl_complete(const QString &, const QString &); void sig_preview_gdl(const QString &, const QString &); }; #endif