root/trunk/qt4-gui/src/dialogs/filedlg.cpp

Revision 6537, 14.3 kB (checked in by flynd, 7 weeks ago)

Added missing include, this caused build to fail on OpenBSD.

  • Property svn:eol-style set to native
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of Licq, an instant messaging client for UNIX.
4 * Copyright (C) 1999-2006 Licq developers
5 *
6 * Licq is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Licq is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Licq; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 */
20
21#include "filedlg.h"
22
23#include "config.h"
24
25#include <unistd.h>
26
27#ifdef USE_KDE
28#include <kfiledialog.h>
29#include <krun.h>
30#else
31#include <QFileDialog>
32#endif
33
34#include <QDir>
35#include <QFrame>
36#include <QGridLayout>
37#include <QHBoxLayout>
38#include <QLabel>
39#include <QProgressBar>
40#include <QPushButton>
41#include <QSocketNotifier>
42#include <QTextCodec>
43
44#include <licq_filetransfer.h>
45#include <licq_icqd.h>
46#include <licq_log.h>
47#include <licq_packets.h>
48#include <licq_translate.h>
49
50#include "core/messagebox.h"
51
52#include "helpers/usercodec.h"
53
54#include "widgets/infofield.h"
55#include "widgets/mledit.h"
56
57using namespace LicqQtGui;
58/* TRANSLATOR LicqQtGui::FileDlg */
59
60FileDlg::FileDlg(const char* szId, unsigned long nPPID, QWidget* parent)
61  : QWidget(parent),
62    myId(szId),
63    m_nPPID(nPPID)
64{
65  setObjectName("FileDialog");
66  setAttribute(Qt::WA_DeleteOnClose, true);
67  setWindowTitle(tr("Licq - File Transfer (%1)").arg(myId));
68
69  unsigned short CR = 0;
70  QGridLayout* lay = new QGridLayout(this);
71  lay->setColumnStretch(1, 2);
72
73  lblTransferFileName = new QLabel(tr("Current:"));
74  lay->addWidget(lblTransferFileName, CR, 0);
75  nfoTransferFileName = new InfoField(true);
76  nfoTransferFileName->setMinimumWidth(nfoTransferFileName->sizeHint().width()*2);
77  lay->addWidget(nfoTransferFileName, CR, 1);
78  nfoTotalFiles = new InfoField(true);
79  nfoTotalFiles->setMinimumWidth((nfoTotalFiles->sizeHint().width()*3)/2);
80  lay->addWidget(nfoTotalFiles, CR, 2);
81
82  lblLocalFileName = new QLabel(tr("File name:"));
83  lay->addWidget(lblLocalFileName, ++CR, 0);
84  nfoLocalFileName = new InfoField(true);
85  lay->addWidget(nfoLocalFileName, CR, 1, 1, 2);
86
87  lay->addItem(new QSpacerItem(0, 10), ++CR, 0);
88
89  // Information stuff about the current file
90  lblTrans = new QLabel(tr("File:"));
91  lay->addWidget(lblTrans, ++CR, 0);
92  barTransfer = new QProgressBar();
93  lay->addWidget(barTransfer, CR, 1);
94  nfoFileSize = new InfoField(true);
95  lay->addWidget(nfoFileSize, CR, 2);
96
97  // Information about the batch file transfer
98  lblBatch = new QLabel(tr("Batch:"));
99  lay->addWidget(lblBatch, ++CR, 0);
100  barBatchTransfer = new QProgressBar();
101  lay->addWidget(barBatchTransfer, CR, 1);
102  nfoBatchSize = new InfoField(true);
103  lay->addWidget(nfoBatchSize, CR, 2);
104
105  lblTime = new QLabel(tr("Time:"));
106  lay->addWidget(lblTime, ++CR, 0);
107
108  QHBoxLayout* hbox = new QHBoxLayout();
109  hbox->setSpacing(8);
110  lay->addLayout(hbox, CR, 0, 1, 2);
111  nfoTime = new InfoField(true);
112  hbox->addWidget(nfoTime);
113  nfoBPS = new InfoField(true);
114  hbox->addWidget(nfoBPS);
115  lblETA = new QLabel(tr("ETA:"));
116  hbox->addWidget(lblETA);
117
118  nfoETA = new InfoField(true);
119  lay->addWidget(nfoETA, CR++, 2);
120  lay->addItem(new QSpacerItem(0, 10), ++CR, 0);
121
122  mleStatus = new MLEdit(true);
123  mleStatus->setReadOnly(true);
124  ++CR;
125  lay->addWidget(mleStatus, CR, 0, 1, 3);
126  mleStatus->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
127
128  lay->addItem(new QSpacerItem(0, 3), ++CR, 0);
129
130  hbox = new QHBoxLayout();
131  hbox->setSpacing(8);
132  lay->addLayout(hbox, CR, 0, 1, 3);
133
134  btnCancel = new QPushButton(tr("&Cancel Transfer"));
135  btnCancel->setMinimumWidth(75);
136  connect(btnCancel, SIGNAL(clicked()), SLOT(close()));
137  hbox->addWidget(btnCancel);
138
139  //TODO fix this
140  ftman = new CFileTransferManager(gLicqDaemon, myId.toULong());
141  ftman->SetUpdatesEnabled(2);
142  sn = new QSocketNotifier(ftman->Pipe(), QSocketNotifier::Read);
143  connect(sn, SIGNAL(activated(int)), SLOT(slot_ft()));
144
145  #ifdef USE_KDE
146    btnOpen = new QPushButton(tr("&Open"));
147    btnOpenDir = new QPushButton(tr("O&pen Dir"));
148    btnOpen->hide();
149    btnOpenDir->hide();
150    connect(btnOpen, SIGNAL(clicked()), SLOT(slot_open()));
151    connect(btnOpenDir, SIGNAL(clicked()), SLOT(slot_opendir()));
152  hbox->addWidget(btnOpen);
153  hbox->addWidget(btnOpenDir);
154  #else
155    btnOpen = 0;
156    btnOpenDir = 0;
157  #endif
158}
159
160
161//-----Destructor---------------------------------------------------------------
162FileDlg::~FileDlg()
163{
164  delete sn;
165  delete ftman;
166}
167
168
169unsigned short FileDlg::LocalPort()
170{
171  return ftman->LocalPort();
172}
173
174
175//-----fileCancel---------------------------------------------------------------
176void FileDlg::slot_cancel()
177{
178  // close the local file and other stuff
179  if (sn != NULL) sn->setEnabled(false);
180  mleStatus->append(tr("File transfer cancelled."));
181  btnCancel->setText(tr("Close"));
182  ftman->CloseFileTransfer();
183}
184
185//-----open button--------------------------------------------------------------
186void FileDlg::slot_open()
187{
188  #ifdef USE_KDE
189    new KRun ("file:" + nfoLocalFileName->text(), 0, true, true);
190  #endif
191}
192
193//-----open directory-----------------------------------------------------------
194void FileDlg::slot_opendir()
195{
196  #ifdef USE_KDE
197    new KRun ("file:" + nfoLocalFileName->text().replace(QRegExp("/[^/]*$"),""),
198        0, true, true);
199  #endif
200}
201
202//-----fileUpdate---------------------------------------------------------------
203void FileDlg::slot_update()
204{
205  //update time, BPS and eta
206  static char sz[16];
207
208  // Current File
209
210  // Transfered
211  nfoFileSize->setText(QString("%1/%2")
212      .arg(encodeFSize(ftman->FilePos()))
213      .arg(encodeFSize(ftman->FileSize())));
214
215  // Time
216  time_t nTime = time(NULL) - ftman->StartTime();
217  unsigned long nBytesTransfered = ftman->BytesTransfered();
218  sprintf(sz, "%02lu:%02lu:%02lu", (unsigned long)(nTime / 3600), (unsigned long)((nTime % 3600) / 60), (unsigned long)((nTime % 60)));
219  nfoTime->setText(sz);
220  if (nTime == 0 || nBytesTransfered == 0)
221  {
222    nfoBPS->setText("---");
223    nfoETA->setText("---");
224    return;
225  }
226
227  // BPS
228  nfoBPS->setText(QString("%1/s").arg(encodeFSize(nBytesTransfered / nTime)));
229
230  // ETA
231  int nBytesLeft = ftman->FileSize() - ftman->FilePos();
232  time_t nETA = (time_t)(nBytesLeft / (nBytesTransfered / nTime));
233  sprintf(sz, "%02lu:%02lu:%02lu", (unsigned long)(nETA / 3600), (unsigned long)((nETA % 3600) / 60), (unsigned long)((nETA % 60)));
234  nfoETA->setText(sz);
235
236  // Batch
237
238  // Transfered
239  nfoBatchSize->setText(QString(tr("%1/%2"))
240     .arg(encodeFSize(ftman->BatchPos())).arg(encodeFSize(ftman->BatchSize())));
241
242
243  barTransfer->setValue(ftman->FilePos() / 1024);
244  barBatchTransfer->setValue(ftman->BatchPos() / 1024);
245}
246
247
248
249
250//-----ReceiveFiles----------------------------------------------------------
251bool FileDlg::ReceiveFiles()
252{
253  // Get the local directory to save to
254  QString d;
255#ifdef USE_KDE
256  d = KFileDialog::getExistingDirectory(QString(QDir::homePath()), this);
257#else
258  d = QFileDialog::getExistingDirectory(this, QString(), QDir::homePath());
259#endif
260  if (d.isNull()) return false;
261
262  // Cut trailing slash
263  if (d.right(1) == "/") d.truncate(d.length()-1);
264
265  if (!ftman->ReceiveFiles(QFile::encodeName(d))) return false;
266
267  mleStatus->append(tr("Waiting for connection..."));
268  show();
269  return true;
270}
271
272
273//-----FileDlg::slot_ft-----------------------------------------------------
274void FileDlg::slot_ft()
275{
276  // Read out any pending events
277  char buf[32];
278  read(ftman->Pipe(), buf, 32);
279
280  QTextCodec* codec = UserCodec::codecForProtoUser(myId, m_nPPID);
281
282  CFileTransferEvent* e = NULL;
283  while ( (e = ftman->PopFileTransferEvent()) != NULL)
284  {
285    switch(e->Command())
286    {
287      case FT_STARTxBATCH:
288      {
289        setWindowTitle(QString(tr("Licq - File Transfer (%1)")).arg(codec->toUnicode(ftman->RemoteName())));
290        nfoTotalFiles->setText(QString("%1 / %2").arg(1).arg(ftman->BatchFiles()));
291        nfoBatchSize->setText(encodeFSize(ftman->BatchSize()));
292        barBatchTransfer->setMaximum(ftman->BatchSize() / 1024);
293        barBatchTransfer->setValue(0);
294        break;
295      }
296
297      case FT_CONFIRMxFILE:
298      {
299        // Use this opportunity to encode the filename
300        ftman->StartReceivingFile(QFile::encodeName(codec->toUnicode(ftman->FileName())).data());
301        break;
302      }
303
304      case FT_STARTxFILE:
305      {
306        nfoTotalFiles->setText(QString("%1 / %2").arg(ftman->CurrentFile()).arg(ftman->BatchFiles()));
307        nfoTransferFileName->setText(QFile::decodeName(ftman->FileName()));
308        nfoLocalFileName->setText(QFile::decodeName(ftman->PathName()));
309        nfoFileSize->setText(encodeFSize(ftman->FileSize()));
310        barTransfer->setMaximum(ftman->FileSize() / 1024);
311        if (ftman->Direction() == D_RECEIVER)
312          mleStatus->append(tr("Receiving file..."));
313        else
314          mleStatus->append(tr("Sending file..."));
315        break;
316      }
317
318      case FT_UPDATE:
319      {
320        slot_update();
321        break;
322      }
323
324      case FT_DONExFILE:
325      {
326        slot_update();
327        if (ftman->Direction() == D_RECEIVER)
328          mleStatus->append(tr("Received %1 from %2 successfully.").arg(QFile::decodeName(e->Data())).arg(codec->toUnicode(ftman->RemoteName())));
329        else
330          mleStatus->append(tr("Sent %1 to %2 successfully.").arg(QFile::decodeName(e->Data())).arg(codec->toUnicode(ftman->RemoteName())));
331        break;
332      }
333
334      case FT_DONExBATCH:
335      {
336        mleStatus->append(tr("File transfer complete."));
337        btnCancel->setText(tr("OK"));
338        if (btnOpen && btnOpenDir && ftman->Direction() == D_RECEIVER)
339        {
340          btnOpen->show();
341          btnOpenDir->show();
342        }
343
344        ftman->CloseFileTransfer();
345        break;
346      }
347
348      case FT_ERRORxCLOSED:
349      {
350        btnCancel->setText(tr("Close"));
351        mleStatus->append(tr("Remote side disconnected."));
352        ftman->CloseFileTransfer();
353        WarnUser(this, tr("Remote side disconnected."));
354        break;
355      }
356
357      case FT_ERRORxFILE:
358      {
359        btnCancel->setText(tr("Close"));
360        mleStatus->append(tr("File I/O error: %1.").arg(QFile::decodeName(ftman->PathName())));
361        ftman->CloseFileTransfer();
362        WarnUser(this, tr("File I/O Error:\n%1\n\nSee Network Window for details.")
363           .arg(QFile::decodeName(ftman->PathName())));
364        break;
365      }
366
367      case FT_ERRORxHANDSHAKE:
368      {
369        btnCancel->setText(tr("Close"));
370        mleStatus->appendNoNewLine(tr("Handshaking error.\n"));
371        ftman->CloseFileTransfer();
372        WarnUser(this, tr("Handshake Error.\nSee Network Window for details."));
373        break;
374      }
375
376      case FT_ERRORxCONNECT:
377      {
378        btnCancel->setText(tr("Close"));
379        mleStatus->appendNoNewLine(tr("Connection error.\n"));
380        ftman->CloseFileTransfer();
381        WarnUser(this,
382          tr("Unable to reach remote host.\nSee Network Window for details."));
383        break;
384      }
385
386      case FT_ERRORxBIND:
387      {
388        btnCancel->setText(tr("Close"));
389        mleStatus->appendNoNewLine(tr("Bind error.\n"));
390        ftman->CloseFileTransfer();
391        WarnUser(this,
392          tr("Unable to bind to a port.\nSee Network Window for details."));
393        break;
394      }
395
396      case FT_ERRORxRESOURCES:
397      {
398        btnCancel->setText(tr("Close"));
399        mleStatus->appendNoNewLine(tr("Not enough resources.\n"));
400        ftman->CloseFileTransfer();
401        WarnUser(this,
402          tr("Unable to create a thread.\nSee Network Window for details."));
403        break;
404      }
405    }
406
407    delete e;
408  }
409}
410
411
412
413//-----FileDlg::SendFiles---------------------------------------------------
414bool FileDlg::SendFiles(ConstFileList fl, unsigned short nPort)
415{
416  ftman->SendFiles(fl, nPort);
417
418  mleStatus->append(tr("Connecting to remote..."));
419  show();
420  return true;
421}
422
423
424// -----------------------------------------------------------------------------
425
426QString FileDlg::encodeFSize(unsigned long size)
427{
428  QString unit;
429  if(size >= 1024*1024) {
430    size /= (1024*1024)/10;
431    unit = tr("MB");
432  }
433  else if(size >= 1024) {
434    size /= 1024/10;
435    unit = tr("KB");
436  }
437  else if(size != 1) {
438    size *= 10;
439    unit = tr("Bytes");
440  }
441  else {
442    size *= 10;
443    unit = tr("Byte");
444  }
445
446  return QString("%1.%2 %3").arg(size/10).arg(size%10).arg(unit);
447}
448
449#if 0
450//-----GetLocalFileName---------------------------------------------------------
451// Sets the local filename and opens the file
452// returns false if the user hits cancel
453bool FileDlg::GetLocalFileName()
454{
455  QString f;
456  bool bValid = false;
457
458  QTextCodec *codec = UserCodec::codecForProtoUser(m_szId, m_nPPID);
459
460  // Get the local filename and open it, loop until valid or cancel
461  while(!bValid)
462  {
463#ifdef USE_KDE
464    KURL u = KFileDialog::getSaveURL(
465          QString(QDir::homeDirPath() + "/" + codec->toUnicode(m_sFileInfo.szName)),
466          QString::null, this);
467    f = u.path();
468#else
469    f = QFileDialog::getSaveFileName(0, QString(),
470          QString(QDir::homeDirPath() + "/" + codec->toUnicode(m_sFileInfo.szName)),
471          QString::null, this);
472#endif
473    if (f.isNull()) return (false);
474    struct stat buf;
475    int nFlags = O_WRONLY;
476    m_nFilePos = 0;
477    if (stat(QFile::encodeName(f), &buf) == 0)  // file already exists
478    {
479      if ((unsigned long)buf.st_size >= m_sFileInfo.nSize)
480      {
481        if(QueryUser(this, tr("File already exists and is at least as big as the incoming file."), tr("Overwrite"), tr("Cancel")))
482          nFlags |= O_TRUNC;
483        else
484          return (false);
485      }
486      else
487      {
488        if (QueryUser(this, tr("File already exists and appears incomplete."), tr("Overwrite"), tr("Resume")))
489          nFlags |= O_TRUNC;
490        else
491        {
492          nFlags |= O_APPEND;
493          m_nFilePos = buf.st_size;
494        }
495      }
496    }
497    else
498    {
499      nFlags |= O_CREAT;
500    }
501
502    m_nFileDesc = open (QFile::encodeName(f), nFlags, 00664);
503    if (m_nFileDesc < 0)
504    {
505      if (!QueryUser(this, tr("Open error - unable to open file for writing."), tr("Retry"), tr("Cancel")))
506        return (false);
507    }
508    else
509      bValid = true;
510  }
511
512  nfoLocalFileName->setText(f);
513  m_nBytesTransfered = 0;
514  barTransfer->setTotalSteps(m_sFileInfo.nSize / 1024);
515  barTransfer->setProgress(0);
516  return(true);
517}
518#endif
Note: See TracBrowser for help on using the browser.