1 /***************************************************************************
2 * *
3 * This program is free software; you can redistribute it and/or modify *
4 * it under the terms of the GNU General Public License as published by *
5 * the Free Software Foundation; either version 3 of the License, or *
6 * (at your option) any later version. *
7 * *
8 ***************************************************************************/
9
10 #include "HashProgress.h"
11 #include "WulforUtil.h"
12
13 #include <QDir>
14
15 #include "dcpp/stdinc.h"
16 #include "dcpp/HashManager.h"
17 #include "dcpp/ShareManager.h"
18 #include "dcpp/TimerManager.h"
19
20 using namespace dcpp;
21
getHashStatus()22 unsigned HashProgress::getHashStatus() {
23 ShareManager *SM = ShareManager::getInstance();
24 HashManager *HM = HashManager::getInstance();
25 if( SM->isRefreshing() )
26 return LISTUPDATE;
27
28 if( HM->isHashingPaused() ) {
29 return (Util::getUpTime() < SETTING(HASHING_START_DELAY)) ? DELAYED : PAUSED;
30 }
31
32 string path;
33 int64_t bytes = 0;
34 size_t files = 0;
35 HM->getStats(path, bytes, files);
36
37 if( bytes || files )
38 return RUNNING;
39
40 return IDLE;
41 }
42
HashProgress(QWidget * parent)43 HashProgress::HashProgress(QWidget *parent):
44 QDialog(parent),
45 autoClose(false),
46 startBytes(0),
47 startFiles(0),
48 startTime(0)
49 {
50 setupUi(this);
51
52 setWindowModality(Qt::ApplicationModal);
53 setAttribute( Qt::WA_QuitOnClose, false ); // Very important, wo this line app exits then hide
54
55 HashManager::getInstance()->setPriority(Thread::NORMAL);
56
57 timer = new QTimer();
58 timer->setInterval(250);
59
60 connect(timer, SIGNAL(timeout()), this, SLOT(timerTick()));
61 connect(pushButton_START, SIGNAL(clicked()), this, SLOT(slotStart()));
62 connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(slotAutoClose(bool)));
63
64 timer->start();
65 }
66
resetProgress()67 void HashProgress::resetProgress() {
68 startBytes = 0;
69 startFiles = 0;
70 startTime = 0;
71 }
72
~HashProgress()73 HashProgress::~HashProgress(){
74 timer->stop();//really need?
75
76 delete timer;
77
78 HashManager::getInstance()->setPriority(Thread::LOW);
79 }
80
getProgress()81 float HashProgress::getProgress() {
82 return static_cast<float>( progress->value() )/progress->maximum();
83 }
84
timerTick()85 void HashProgress::timerTick(){
86 string path;
87 int64_t bytes = 0;
88 size_t files = 0;
89 uint64_t tick = GET_TICK();
90
91 stateButton();
92
93 HashManager::getInstance()->getStats(path, bytes, files);
94 if(ShareManager::getInstance()->isRefreshing()) {
95 file->setText(tr("Refreshing file list"));
96 return;
97 }
98
99 if( startTime == 0 )
100 startTime = tick;
101
102 if(bytes > startBytes)
103 startBytes = bytes;
104
105 if(files > startFiles)
106 startFiles = files;
107
108 if(autoClose && !files) {
109 accept();
110
111 return;;
112 }
113
114 double diff = tick - startTime;
115 bool paused = HashManager::getInstance()->isHashingPaused();
116
117 QString eta;
118
119 if(startFiles == 0 || startBytes == 0)
120 progress->setValue(0);
121 else
122 progress->setValue( (10000*(startBytes - bytes))/startBytes);
123
124 if( diff == 0. || files == 0 || bytes == 0 || paused) {
125 status->setText(QString(tr("-.-- files/h, %1 files left")).arg((uint32_t)files));
126 speed->setText(tr("-.-- B/s, %1 left").arg(WulforUtil::formatBytes(bytes)));
127 eta = tr("-:--:--");
128 } else {
129 double filestat = (((double)(startFiles - files)) * 60 * 60 * 1000) / diff;
130 double speedStat = (((double)(startBytes - bytes)) * 1000) / diff;
131
132 status->setText(tr("%1 files/h, %2 files left").arg(filestat).arg((uint32_t)files));
133 speed->setText(tr("%1/s, %2 left, %3 shared").arg(WulforUtil::formatBytes((int64_t)speedStat))
134 .arg(WulforUtil::formatBytes(bytes))
135 .arg(WulforUtil::formatBytes(ShareManager::getInstance()->getShareSize())));
136
137 if(/*filestat == 0 ||*/ speedStat == 0) {
138 eta = tr("-:--:--");
139 }
140 else {
141 double ss = bytes / speedStat;
142
143 eta = _q(Text::toT(Util::formatSeconds((int64_t)(ss))));
144 }
145 }
146 progress->setFormat( tr("%p% %1 left").arg(eta) );
147
148 if(!files) {
149 //progress->setValue(10000); // generates anoying blinking 0 -> 100%
150 file->setText(tr("Done"));
151 } else {
152 QString fname = QString::fromStdString(path);
153 QFontMetrics metrics(font());
154
155 file->setToolTip(fname);
156
157 if (metrics.width(fname) > file->width()*3/4){
158 QStringList parts = fname.split(QDir::separator(), QString::SkipEmptyParts);
159
160 if (parts.size() > 1){
161 QString out = "";
162
163 for (int i = (parts.size()-1); i >= 0; i--){
164 if (metrics.width(out+parts.at(i)+QDir::separator()) < file->width()*3/4){
165 out = parts.at(i) + (out.isEmpty()? out : (QDir::separator() + out));
166 }
167 else{
168 out = QString("..") + QDir::separator() + out;
169
170 break;
171 }
172 }
173
174 if (out.isEmpty())
175 out = parts.last();
176
177 fname = out;
178 }
179 }
180
181 file->setText(fname);
182 }
183 }
184
slotStart()185 void HashProgress::slotStart(){
186 ShareManager *SM = ShareManager::getInstance();
187 HashManager *HM = HashManager::getInstance();
188 switch( getHashStatus() ) {
189 case IDLE:
190 SM->setDirty();
191 SM->refresh(true);
192 break;
193 case LISTUPDATE:
194 case RUNNING:
195 HM->pauseHashing();
196 //HM->setPriority(Thread::IDLE);
197 break;
198 case DELAYED:
199 case PAUSED:
200 HM->resumeHashing();
201 //HM->setPriority(Thread::NORMAL);
202 break;
203 }
204 stateButton();
205 }
206
slotAutoClose(bool b)207 void HashProgress::slotAutoClose(bool b){
208 autoClose = b;
209
210 blockSignals(true);
211 checkBox->setChecked(b);
212 blockSignals(false);
213 }
214
stateButton()215 void HashProgress::stateButton(){
216 switch( getHashStatus() ) {
217 case IDLE:
218 pushButton_START->setText(tr("Start"));
219 break;
220 case LISTUPDATE:
221 case RUNNING:
222 pushButton_START->setText(tr("Pause"));
223 break;
224 case DELAYED:
225 case PAUSED:
226 pushButton_START->setText(tr("Resume"));
227 break;
228 }
229 }
230