Commit graph

5554 commits

Author SHA1 Message Date
Ivan Sorokin
9023232653 Cache icons in TorrentContentModel
This commit caches icons in TorrentContentModel in the same way they are
cached in TorrentModel.

This commit should improve performance when user navigating through
torrent list using up/down keys. A scrolling through all the list
(276 torrents) took:

    Total wall time:                            18.813s
    Total CPU time:                              3.210s
    IconProvider::generateDifferentSizes():      0.170s

IconProvider::generateDifferentSizes is 5th most hottest function on
this use case.
2014-11-09 12:57:14 +03:00
Ivan Sorokin
976982ba09 Now user-created labels "all" and "none" works as regular labels 2014-11-09 03:59:49 +03:00
Ivan Sorokin
f235c0ae6c Merge label filter into TransferListSortModel
This also fixes a bug that when label filter contains special symbols
from regex, the label filter may match torrents with multiple different
labels.
2014-11-09 03:58:50 +03:00
Ivan Sorokin
8bafc5e216 Merge StatusSortFilterProxyModel into TransferListSortModel
I thought merging all 3 sort-filter proxy models into one should
speedup dataChanged() signal. As turned out this is not the case. The
time difference is within inaccuracy range, so this doesn't affect
performance.

But I still think it is good to merge them into one proxy model as it
simplifies code.
2014-11-09 03:58:50 +03:00
Ivan Sorokin
cf2cb29826 Split transferlistsortmodel into .h and .cpp 2014-11-09 03:58:50 +03:00
Ivan Sorokin
0976918ca2 Call updateTorrentNumbers() once per every model refresh, not once for every row changed
Torrent numbers were recalculated on every dataChanged() signal. The previous commit
greatly increases the number of dataChanged() signals.

HEAD^^:
    Total wall clock:                 97.069s
    updateTorrentNumbers() time:       0.033s

HEAD^:
    Total wall clock:                 96.132s
    updateTorrentNumbers() time:       0.179s

HEAD:
    Total wall clock:                 95.535s
    updateTorrentNumbers() time:       0.047s

After this commit the time of updateTorrentNumbers() is (almost) back to
the level that it was in HEAD^^.
2014-11-09 03:58:50 +03:00
Ivan Sorokin
e5c024967d Emit TorrentModel::dataChanged() signal only for specific rows, not for the entire table
In commit b50d733 TorrentModel moved from a periodic refresh, to using
postStatusUpdate(). In this transition I forgot to remove emition of
dataChanged() signal for the entire table.

According to my measurements this commit reduce CPU usage of qbittorrent
by a factor of 3:

Before:
   Total wall clock:                                      97.07s
   CPU time:                                              21.77s
   - Time spent in TransferListDelegate::paint():         14.60s
   - Time spent in TorrentModel::forceModelRefresh():      1.44s
   - Time spent in TorrentModel::stateUpdated():           0.02s

After:
   Total wall clock:                                      96.13s
   CPU time:                                               6.68s
   - Time spent in TransferListDelegate::paint():          2.63s
   - Time spent in TorrentModel::forceModelRefresh():     <0.01s
   - Time spent in TorrentModel::stateUpdated():           1.73s

As it is seen the time spent in painting is reduced by a factor of 6 (14.60->2.63) at
the cost of slightly increased time of notifications that model is
changed (1.44->1.73). The next commits attempt to address this issue.
2014-11-09 03:58:50 +03:00
Ivan Sorokin
2e55c1f307 Optimize torrentRow a bit
The problem is that torrentRow() does linear search over the list of all
available torrents. So it doesn't scale well for large number of
torrents. Removing the copying of QString from linear search
inner loop, speed up it considerably.

The proper solution should be using hash table instead of linear search.
This require more radical changes in TorrentModel and may be done in a
separate commit.
2014-11-09 03:48:58 +03:00
sledgehammer999
a07f25aa67 Merge pull request #2124 from pmzqla/webui
Misc changes to the WebUI
2014-11-09 01:51:38 +02:00
Gabriele
97c1b17cf0 Show a spinner while torrents are being uploaded 2014-11-09 00:30:37 +01:00
Gabriele
3d1617b2de Upload torrents on user command
Don't upload the torrents as soon as they are selected.

Also, adjust the HTML code to better place the upload button.
2014-11-09 00:28:41 +01:00
Gabriele
ee3a736787 WebUI: Return error in case uploaded files are not torrents 2014-11-09 00:28:41 +01:00
Gabriele
8b8c9d3573 Rotate expand image to better suit its use in the UI 2014-11-09 00:28:36 +01:00
Gabriele
c255ba675a Center images in top menu 2014-11-09 00:28:18 +01:00
Gabriele
7b49ab2a48 Add missing images and fix few paths
These images are used in CSS rules, but are missing.

Images taken from MochaUI git repo.
2014-11-09 00:28:18 +01:00
Gabriele
465ff473f1 Drop Firefox specific code
This change improves the responsiveness while resizing panels.
The code was intended to fix bugs in really old versions of Firefox.
2014-11-09 00:28:18 +01:00
Gabriele
e83e46b08a Fix panel height calculation in Opera 2014-11-09 00:28:18 +01:00
Gabriele
7b73e96863 Fix errors in width and height calculations
border-left/right/top/bottom are not numbers.
2014-11-09 00:28:18 +01:00
Gabriele
dc0591997a Bump Internet Explorer compatibility 2014-11-09 00:28:18 +01:00
Gabriele
30a25e1de4 Workaround to make invisible buttons clickable on IE 2014-11-09 00:28:18 +01:00
Gabriele
d106c12aa2 Restricts hacks and workarounds to IE < 9 2014-11-09 00:28:18 +01:00
Gabriele
66a91a6e3a Remove XML encoding declaration from HTML files 2014-11-09 00:27:53 +01:00
Gabriele
0d2e9a9473 Reduce font size of priority combo boxes
They were too big in some cases (e.g. Firefox on Linux).
2014-11-09 00:25:40 +01:00
Gabriele
fa706b24be Use fake tristate checkbox on IE < 9 only 2014-11-09 00:25:40 +01:00
Gabriele
92cc8f7211 Fix disappearing transferlist list when zooming in the browser
When the page is zoomed in the browser, the transferlist doesn't fit
in the page and is moved below the left column, disappearing completely.

Allow elements to overlap the handle to prevent this from happening.

The error message is moved in the status bar since it's wrongly placed
because of the overlap.

Closes #603.
2014-11-09 00:25:40 +01:00
Gabriele
4f28fb5680 Minimize width of first column in transfer list 2014-11-09 00:25:40 +01:00
Gabriele
afde16c252 Change color of table header in bottom panel and add some padding 2014-11-09 00:25:40 +01:00
Gabriele
c516c0ac12 Center vertically "+" image in tracker list 2014-11-09 00:25:40 +01:00
Gabriele
af9e40d83d Alternate background color for torrent content
CSS3 support required.
2014-11-09 00:25:40 +01:00
Gabriele
b01c1f3b9a Don't show white parts when hovering over the elements of the menu 2014-11-09 00:25:40 +01:00
Gabriele
4ff999d1c5 Change background color of rows of torrent content 2014-11-09 00:25:40 +01:00
Gabriele
c9db08f0f4 Change background color of filterlist on hover 2014-11-09 00:25:40 +01:00
Gabriele
59abcc554d Remove "Downloaded" from transferlist header and reduce column width 2014-11-09 00:25:40 +01:00
Gabriele
863dc71100 Focus username input on load 2014-11-09 00:25:40 +01:00
Gabriele
0bfad7dce6 Add type attribute to style tag 2014-11-09 00:25:40 +01:00
Gabriele
5e77d99a5e Add alt attribute to images 2014-11-09 00:25:40 +01:00
Gabriele
b2e86bae7e Remove extra double quotes 2014-11-09 00:25:34 +01:00
sledgehammer999
f5c93e0b4d Merge pull request #2129 from glassez/webui
WebUI Fixes
2014-11-09 01:21:00 +02:00
Ivan Sorokin
c37e5abeff Fix torrent removal. Closes #2132
It was reported that qbittorrent crashes on Mac OS X when user deletes
torrents from label view when label filter is active.

The callstack of the crash is the following:

1   abort + 129
2   __assert_rtn + 321
3   QTorrentHandle::total_size() const + 124
4   TorrentModelItem::data(int, int) const + 307
5   TorrentModel::data(QModelIndex const&, int) const + 255
6   QSortFilterProxyModel::data(QModelIndex const&, int) const + 109
7   QSortFilterProxyModel::data(QModelIndex const&, int) const + 109
8   QSortFilterProxyModel::data(QModelIndex const&, int) const + 109
9   QItemDelegate::rect(QStyleOptionViewItem const&, QModelIndex const&, int) const + 75
10  QItemDelegate::sizeHint(QStyleOptionViewItem const&, QModelIndex const&) const + 172
11  TransferListDelegate::sizeHint(QStyleOptionViewItem const&, QModelIndex const&) const + 14
12  QTreeView::indexRowSizeHint(QModelIndex const&) const + 887
13  QTreeViewPrivate::layout(int, bool, bool) + 462
14  QTreeView::doItemsLayout() + 356
15  QTreeViewPrivate::updateScrollBars() + 109
16  QTreeView::scrollTo(QModelIndex const&, QAbstractItemView::ScrollHint) + 124
17  TransferListWidget::currentChanged(QModelIndex const&, QModelIndex const&) + 548
18  TransferListWidget::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) + 641
19  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
20  QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(QModelIndex const&, int, int) + 3729
21  QItemSelectionModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) + 398
22  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
23  QAbstractItemModel::rowsAboutToBeRemoved(QModelIndex const&, int, int) + 78
24  QAbstractItemModel::beginRemoveRows(QModelIndex const&, int, int) + 106
25  QSortFilterProxyModelPrivate::remove_proxy_interval(QVector<int>&, QVector<int>&, int, int, QModelIndex const&, Qt::Orientation, bool) + 58
26  QSortFilterProxyModelPrivate::remove_source_items(QVector<int>&, QVector<int>&, QVector<int> const&, QModelIndex const&, Qt::Orientation, bool) + 265
27  QSortFilterProxyModelPrivate::source_items_about_to_be_removed(QModelIndex const&, int, int, Qt::Orientation) + 232
28  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
29  QAbstractItemModel::rowsAboutToBeRemoved(QModelIndex const&, int, int) + 78
30  QAbstractItemModel::beginRemoveRows(QModelIndex const&, int, int) + 106
31  QSortFilterProxyModelPrivate::remove_proxy_interval(QVector<int>&, QVector<int>&, int, int, QModelIndex const&, Qt::Orientation, bool) + 58
32  QSortFilterProxyModelPrivate::remove_source_items(QVector<int>&, QVector<int>&, QVector<int> const&, QModelIndex const&, Qt::Orientation, bool) + 265
33  QSortFilterProxyModelPrivate::source_items_about_to_be_removed(QModelIndex const&, int, int, Qt::Orientation) + 232
34  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
35  QAbstractItemModel::rowsAboutToBeRemoved(QModelIndex const&, int, int) + 78
36  QAbstractItemModel::beginRemoveRows(QModelIndex const&, int, int) + 106
37  QSortFilterProxyModelPrivate::remove_proxy_interval(QVector<int>&, QVector<int>&, int, int, QModelIndex const&, Qt::Orientation, bool) + 58
38  QSortFilterProxyModelPrivate::remove_source_items(QVector<int>&, QVector<int>&, QVector<int> const&, QModelIndex const&, Qt::Orientation, bool) + 265
39  QSortFilterProxyModelPrivate::source_items_about_to_be_removed(QModelIndex const&, int, int, Qt::Orientation) + 232
40  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
41  QAbstractItemModel::rowsAboutToBeRemoved(QModelIndex const&, int, int) + 78
42  QAbstractItemModel::beginRemoveRows(QModelIndex const&, int, int) + 106
43  TorrentModel::removeTorrent(QString const&) + 81
44  TorrentModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) + 345
45  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
46  QBtSession::deletedTorrent(QString const&) + 56
47  QBtSession::deleteTorrent(QString const&, bool) + 2855
48  TransferListWidget::deleteSelectedTorrents() + 292
49  TransferListWidget::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) + 230
50  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
51  QAction::activate(QAction::ActionEvent) + 227
52  QMenuPrivate::activateCausedStack(QList<QPointer<QWidget> > const&, QAction*, QAction::ActionEvent, bool) + 77
53  QMenuPrivate::activateAction(QAction*, QAction::ActionEvent, bool) + 470
54  QWidget::event(QEvent*) + 687
55  QMenu::event(QEvent*) + 617
56  QApplicationPrivate::notify_helper(QObject*, QEvent*) + 194
57  QApplication::notify(QObject*, QEvent*) + 2716
58  SessionApplication::notify(QObject*, QEvent*) + 21
59  QCoreApplication::notifyInternal(QObject*, QEvent*) + 118
60  QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) + 448
61  qt_mac_handleMouseEvent(NSEvent*, QEvent::Type, Qt::MouseButton, QWidget*, bool) + 1300
62  -[NSWindow _reallySendEvent:] + 759
63  -[NSWindow sendEvent:] + 368
64  -[QCocoaPanel sendEvent:] + 113
65  -[NSApplication sendEvent:] + 2238
66  -[QNSApplication sendEvent:] + 97
67  -[NSApplication run] + 711
68  QEventDispatcherMac::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 1522
69  QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 77
70  QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 370
71  QMenu::exec(QPoint const&, QAction*) + 103
72  TransferListWidget::displayListMenu(QPoint const&) + 8741
73  TransferListWidget::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) + 622
74  QMetaObject::activate(QObject*, QMetaObject const*, int, void**) + 2196
75  QWidget::event(QEvent*) + 3082
76  QFrame::event(QEvent*) + 45
77  QAbstractScrollArea::viewportEvent(QEvent*) + 108
78  QAbstractItemView::viewportEvent(QEvent*) + 1390
79  QTreeView::viewportEvent(QEvent*) + 218
80  QAbstractScrollAreaFilter::eventFilter(QObject*, QEvent*) + 37
81  QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) + 115
82  QApplicationPrivate::notify_helper(QObject*, QEvent*) + 178
83  QApplication::notify(QObject*, QEvent*) + 5742
84  SessionApplication::notify(QObject*, QEvent*) + 21
85  QCoreApplication::notifyInternal(QObject*, QEvent*) + 118
86  qt_sendSpontaneousEvent(QObject*, QEvent*) + 45
87  qt_mac_handleMouseEvent(NSEvent*, QEvent::Type, Qt::MouseButton, QWidget*, bool) + 1378
88  -[NSWindow _reallySendEvent:] + 5682
89  -[NSWindow sendEvent:] + 368
90  -[QCocoaWindow sendEvent:] + 113
91  -[NSApplication sendEvent:] + 2238
92  -[QNSApplication sendEvent:] + 97
93  -[NSApplication run] + 711
94  QEventDispatcherMac::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 1522
95  QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 77
96  QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 370
97  QCoreApplication::exec() + 199
98  main + 3415
99  start + 52

As we can see the user deleted some torrent (48). QBtSession deleted the torrent
from libtorrent::session (47) and emitted a signal (46), about torrent deletion.
In responce to the signal (43) the TorrentModel notifies (42) its views about a change.
After a long chain of notifications (42-6) the view requested (5) a value of
total_size from TorrentModel. QTorrentHandle is already invalid as the torrent
was removed in (47). So we've got a crash in (3).

The fix is relatively straightforward: do notify TorrentModel about removal not after,
but before torrent is removed from libtorrent::session. This commit does the same
thing to TorrentSpeedMonitor.

This bug reveals a major flaw in a design: currently we have a several components all
subscribed to the torrent removal signal. Signal is delivered to them in arbitrary
order, but they access each other in the handlers of this signal. E.g. TorrentModel
can access TorrentSpeedMonitor. This doesn't lead to a crash because
TorrentSpeedMonitor returns MAX_ETA when ETA is queried for unknown torrent.
2014-11-09 00:25:59 +03:00
sledgehammer999
3202ad368f Merge pull request #2141 from sorokin/fix-a-warning
Fix a warning
2014-11-08 21:21:43 +02:00
Ivan Sorokin
6bbfd0aeb7 Fix a warning 2014-11-08 19:00:04 +03:00
sledgehammer999
c9e13dfe8b Merge pull request #2120 from sorokin/ip-filter-moc
split filterparserthread into .h and .cpp and (probably) fixes #2119
2014-11-08 14:35:23 +02:00
Vladimir Golovnev (Glassez)
cd0bcacd9f WebUI: Fix upload window closing on old browsers. 2014-11-07 15:53:11 +03:00
Vladimir Golovnev (Glassez)
d85c3170b2 WebUI: Add charset attribute to text content types. 2014-11-05 20:24:17 +03:00
Vladimir Golovnev (Glassez)
7b7f88ae4f WebUI: Fix WebAPI returned data. 2014-11-05 20:24:02 +03:00
Ivan Sorokin
da867fd022 Split trackerlogin into .h and .cpp 2014-11-05 03:10:39 +03:00
Ivan Sorokin
ed197a193d Split statusbar into .h and .cpp 2014-11-05 03:10:39 +03:00
Ivan Sorokin
6347700ee3 Move libtorrent includes to .cpp
This commit probably fixes #2119.

The only important change in this commit is moving
session::get_ip_filter() from FilterParserThread::processFilterFile() to
FilterParserThread::run(). Previously we called it in main thread, but
now we calls it in worker thread. I don't now what libtorrent contract
about threads, but I assume that if it is ok to set_ip_filter from
other thread, it is ok to get it.
2014-11-05 03:10:39 +03:00
Ivan Sorokin
17f5ffcaec Split filterparserthread into .h and .cpp 2014-11-05 03:10:39 +03:00
sledgehammer999
a63d4e3400 Merge pull request #2117 from glassez/webui
WebUI Fixes
2014-11-03 17:00:34 +02:00