1 /*
2  * Bittorrent Client using Qt and libtorrent.
3  * Copyright (C) 2015 Anton Lashkov <lenton_91@mail.ru>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  * In addition, as a special exception, the copyright holders give permission to
20  * link this program with the OpenSSL project's "OpenSSL" library (or with
21  * modified versions of it that use the same license as the "OpenSSL" library),
22  * and distribute the linked executables. You must obey the GNU General Public
23  * License in all respects for all of the code used other than "OpenSSL".  If you
24  * modify file(s), you may extend this exception to your version of the file(s),
25  * but you are not obligated to do so. If you do not wish to do so, delete this
26  * exception statement from your version.
27  */
28 
29 #include "speedwidget.h"
30 
31 #include <QDateTime>
32 #include <QHBoxLayout>
33 #include <QLabel>
34 #include <QMenu>
35 #include <QTimer>
36 #include <QVBoxLayout>
37 
38 #include "base/bittorrent/session.h"
39 #include "base/bittorrent/sessionstatus.h"
40 #include "base/preferences.h"
41 #include "propertieswidget.h"
42 #include "speedplotview.h"
43 
ComboBoxMenuButton(QWidget * parent,QMenu * menu)44 ComboBoxMenuButton::ComboBoxMenuButton(QWidget *parent, QMenu *menu)
45     : QComboBox(parent)
46     , m_menu(menu)
47 {
48 }
49 
showPopup()50 void ComboBoxMenuButton::showPopup()
51 {
52     const QPoint p = mapToGlobal(QPoint(0, height()));
53     m_menu->popup(p);
54 
55     QComboBox::hidePopup();
56 }
57 
SpeedWidget(PropertiesWidget * parent)58 SpeedWidget::SpeedWidget(PropertiesWidget *parent)
59     : QWidget(parent)
60 {
61     m_layout = new QVBoxLayout(this);
62     m_layout->setContentsMargins(0, 0, 0, 0);
63     m_layout->setSpacing(3);
64 
65     m_hlayout = new QHBoxLayout();
66     m_hlayout->setContentsMargins(0, 0, 0, 0);
67 
68     m_periodLabel = new QLabel("<b>" + tr("Period:") + "</b>");
69 
70     m_periodCombobox = new QComboBox();
71     m_periodCombobox->addItem(tr("1 Minute"));
72     m_periodCombobox->addItem(tr("5 Minutes"));
73     m_periodCombobox->addItem(tr("30 Minutes"));
74     m_periodCombobox->addItem(tr("3 Hours"));
75     m_periodCombobox->addItem(tr("6 Hours"));
76     m_periodCombobox->addItem(tr("12 Hours"));
77     m_periodCombobox->addItem(tr("24 Hours"));
78 
79     connect(m_periodCombobox, qOverload<int>(&QComboBox::currentIndexChanged)
80         , this, &SpeedWidget::onPeriodChange);
81 
82     m_graphsMenu = new QMenu(this);
83     m_graphsMenu->addAction(tr("Total Upload"));
84     m_graphsMenu->addAction(tr("Total Download"));
85     m_graphsMenu->addAction(tr("Payload Upload"));
86     m_graphsMenu->addAction(tr("Payload Download"));
87     m_graphsMenu->addAction(tr("Overhead Upload"));
88     m_graphsMenu->addAction(tr("Overhead Download"));
89     m_graphsMenu->addAction(tr("DHT Upload"));
90     m_graphsMenu->addAction(tr("DHT Download"));
91     m_graphsMenu->addAction(tr("Tracker Upload"));
92     m_graphsMenu->addAction(tr("Tracker Download"));
93 
94     m_graphsMenuActions = m_graphsMenu->actions();
95 
96     for (int id = SpeedPlotView::UP; id < SpeedPlotView::NB_GRAPHS; ++id)
97     {
98         QAction *action = m_graphsMenuActions.at(id);
99         action->setCheckable(true);
100         action->setChecked(true);
101         connect(action, &QAction::changed, this, [this, id]() { onGraphChange(id); });
102     }
103 
104     m_graphsButton = new ComboBoxMenuButton(this, m_graphsMenu);
105     m_graphsButton->addItem(tr("Select Graphs"));
106 
107     m_hlayout->addWidget(m_periodLabel);
108     m_hlayout->addWidget(m_periodCombobox);
109     m_hlayout->addStretch();
110     m_hlayout->addWidget(m_graphsButton);
111 
112     m_plot = new SpeedPlotView(this);
113     connect(BitTorrent::Session::instance(), &BitTorrent::Session::statsUpdated, this, &SpeedWidget::update);
114 
115     m_layout->addLayout(m_hlayout);
116     m_layout->addWidget(m_plot);
117 
118     loadSettings();
119 
120     m_plot->show();
121 }
122 
~SpeedWidget()123 SpeedWidget::~SpeedWidget()
124 {
125     qDebug("SpeedWidget::~SpeedWidget() ENTER");
126     saveSettings();
127     qDebug("SpeedWidget::~SpeedWidget() EXIT");
128 }
129 
update()130 void SpeedWidget::update()
131 {
132     const BitTorrent::SessionStatus &btStatus = BitTorrent::Session::instance()->status();
133 
134     SpeedPlotView::SampleData sampleData;
135     sampleData[SpeedPlotView::UP] = btStatus.uploadRate;
136     sampleData[SpeedPlotView::DOWN] = btStatus.downloadRate;
137     sampleData[SpeedPlotView::PAYLOAD_UP] = btStatus.payloadUploadRate;
138     sampleData[SpeedPlotView::PAYLOAD_DOWN] = btStatus.payloadDownloadRate;
139     sampleData[SpeedPlotView::OVERHEAD_UP] = btStatus.ipOverheadUploadRate;
140     sampleData[SpeedPlotView::OVERHEAD_DOWN] = btStatus.ipOverheadDownloadRate;
141     sampleData[SpeedPlotView::DHT_UP] = btStatus.dhtUploadRate;
142     sampleData[SpeedPlotView::DHT_DOWN] = btStatus.dhtDownloadRate;
143     sampleData[SpeedPlotView::TRACKER_UP] = btStatus.trackerUploadRate;
144     sampleData[SpeedPlotView::TRACKER_DOWN] = btStatus.trackerDownloadRate;
145 
146     m_plot->pushPoint(sampleData);
147 }
148 
onPeriodChange(int period)149 void SpeedWidget::onPeriodChange(int period)
150 {
151     m_plot->setPeriod(static_cast<SpeedPlotView::TimePeriod>(period));
152 }
153 
onGraphChange(int id)154 void SpeedWidget::onGraphChange(int id)
155 {
156     QAction *action = m_graphsMenuActions.at(id);
157     m_plot->setGraphEnable(static_cast<SpeedPlotView::GraphID>(id), action->isChecked());
158 }
159 
loadSettings()160 void SpeedWidget::loadSettings()
161 {
162     Preferences *preferences = Preferences::instance();
163 
164     int periodIndex = preferences->getSpeedWidgetPeriod();
165     m_periodCombobox->setCurrentIndex(periodIndex);
166     onPeriodChange(static_cast<SpeedPlotView::TimePeriod>(periodIndex));
167 
168     for (int id = SpeedPlotView::UP; id < SpeedPlotView::NB_GRAPHS; ++id)
169     {
170         QAction *action = m_graphsMenuActions.at(id);
171         bool enable = preferences->getSpeedWidgetGraphEnable(id);
172 
173         action->setChecked(enable);
174         m_plot->setGraphEnable(static_cast<SpeedPlotView::GraphID>(id), enable);
175     }
176 }
177 
saveSettings() const178 void SpeedWidget::saveSettings() const
179 {
180     Preferences *preferences = Preferences::instance();
181 
182     preferences->setSpeedWidgetPeriod(m_periodCombobox->currentIndex());
183 
184     for (int id = SpeedPlotView::UP; id < SpeedPlotView::NB_GRAPHS; ++id)
185     {
186         QAction *action = m_graphsMenuActions.at(id);
187         preferences->setSpeedWidgetGraphEnable(id, action->isChecked());
188     }
189 }
190