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

Revision 6463, 7.4 kB (checked in by flynd, 4 months ago)

Use a const pointer for user objects that are only fetched for read access. Fixed some places where we changed the user even though we just had a read lock.

  • 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) 2000-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 "mmsenddlg.h"
22
23#include "config.h"
24
25#include <stdio.h>
26#include <unistd.h>
27
28#include <QByteArray>
29#include <QDialogButtonBox>
30#include <QGroupBox>
31#include <QLabel>
32#include <QLayout>
33#include <QProgressBar>
34#include <QPushButton>
35#include <QRegExp>
36#include <QTextCodec>
37#include <QVBoxLayout>
38
39#include <licq_events.h>
40#include <licq_icqd.h>
41#include <licq_translate.h>
42#include <licq_user.h>
43
44#include "core/licqgui.h"
45#include "core/signalmanager.h"
46
47#include "helpers/support.h"
48#include "helpers/usercodec.h"
49
50#include "views/mmuserview.h"
51
52using namespace LicqQtGui;
53/* TRANSLATOR LicqQtGui::MMSendDlg */
54
55MMSendDlg::MMSendDlg(MMUserView* _mmv, QWidget* p)
56  : QDialog(p),
57    mmv(_mmv),
58    m_nPPID(0),
59    icqEventTag(0)
60{
61  Support::setWidgetProps(this, "MMSendDialog");
62  setModal(true);
63  setAttribute(Qt::WA_DeleteOnClose, true);
64
65  QVBoxLayout* v = new QVBoxLayout(this);
66
67  grpSending = new QGroupBox();
68  QVBoxLayout* laySending = new QVBoxLayout(grpSending);
69  barSend = new QProgressBar();
70  laySending->addWidget(barSend);
71
72  QDialogButtonBox* buttons = new QDialogButtonBox();
73  btnCancel = buttons->addButton(QDialogButtonBox::Cancel);
74
75  v->addWidget(grpSending);
76  v->addWidget(buttons);
77
78  connect(btnCancel, SIGNAL(clicked()), SLOT(slot_cancel()));
79  connect(LicqGui::instance()->signalManager(),
80      SIGNAL(doneUserFcn(ICQEvent*)), SLOT(slot_done(ICQEvent*)));
81
82  barSend->setMaximum(mmv->contacts().count());
83  barSend->setValue(0);
84
85  setMinimumWidth(300);
86}
87
88int MMSendDlg::go_message(QString msg)
89{
90  m_nEventType = ICQ_CMDxSUB_MSG;
91  s1 = msg;
92
93  setWindowTitle(tr("Multiple Recipient Message"));
94
95  // Start
96  SendNext();
97  show();
98  return 0;
99}
100
101int MMSendDlg::go_url(QString url, QString desc)
102{
103  m_nEventType = ICQ_CMDxSUB_URL;
104  s1 = desc;
105  s2 = url;
106
107  setWindowTitle(tr("Multiple Recipient URL"));
108
109  // Start
110  SendNext();
111  show();
112  return result();
113}
114
115int MMSendDlg::go_contact(StringList& users)
116{
117  m_nEventType = ICQ_CMDxSUB_CONTACTxLIST;
118  myUsers = &users;
119
120  setWindowTitle(tr("Multiple Recipient Contact List"));
121
122  // Start
123  SendNext();
124  show();
125  return result();
126}
127
128void MMSendDlg::slot_done(ICQEvent* e)
129{
130  if ( !e->Equals(icqEventTag) )
131    return;
132
133  bool isOk = (e != NULL && e->Result() == EVENT_ACKED);
134
135  icqEventTag = 0;
136
137  if (!isOk)
138  {
139    grpSending->setTitle(grpSending->title() + tr("failed"));
140    btnCancel->setText(tr("&Close"));
141    return;
142  }
143
144  // Send next message
145  barSend->setValue(barSend->value() + 1);
146  mmv->removeFirst();
147
148  SendNext();
149}
150
151void MMSendDlg::SendNext()
152{
153  if (mmv->contacts().empty())
154  {
155    accept();
156    return;
157  }
158
159  QPair<QString, unsigned long> contact = *mmv->contacts().begin();
160
161  myId = contact.first;
162  m_nPPID = contact.second;
163
164  if (myId.isEmpty()) return;
165
166  switch (m_nEventType)
167  {
168    case ICQ_CMDxSUB_MSG:
169    {
170      const ICQUser* u = gUserManager.FetchUser(myId.toLatin1(), m_nPPID, LOCK_R);
171      if (u == NULL) return;
172      QTextCodec* codec = UserCodec::codecForICQUser(u);
173      grpSending->setTitle(tr("Sending mass message to %1...").arg(QString::fromUtf8(u->GetAlias())));
174      gUserManager.DropUser(u);
175
176      // create initial strings (implicit copying, no allocation impact :)
177      char* tmp = gTranslator.NToRN(codec->fromUnicode(s1));
178      QByteArray wholeMessageRaw(tmp);
179      delete [] tmp;
180      int wholeMessagePos = 0;
181
182      bool needsSplitting = false;
183      // If we send through server (= have message limit), and we've crossed the limit
184      if ((wholeMessageRaw.length() - wholeMessagePos) > MAX_MESSAGE_SIZE)
185      {
186        needsSplitting = true;
187      }
188
189      QString message;
190      QByteArray messageRaw;
191
192      while (wholeMessageRaw.length() > wholeMessagePos)
193      {
194        if (needsSplitting)
195        {
196          // This is a bit ugly but adds safety. We don't simply search
197          // for a whitespace to cut at in the encoded text (since we don't
198          // really know how spaces are represented in its encoding), so
199          // we take the maximum length, then convert back to a Unicode string
200          // and then search for Unicode whitespaces.
201          messageRaw = wholeMessageRaw.mid(wholeMessagePos, MAX_MESSAGE_SIZE);
202          tmp = gTranslator.RNToN(messageRaw);
203          messageRaw = tmp;
204          delete [] tmp;
205          message = codec->toUnicode(messageRaw);
206
207          if ((wholeMessageRaw.length() - wholeMessagePos) > MAX_MESSAGE_SIZE)
208          {
209            // We try to find the optimal place to cut
210            // (according to our narrow-minded Latin1 idea of optimal :)
211            // prefer keeping sentences intact 1st
212            int foundIndex = message.lastIndexOf(QRegExp("[\\.\\n]"));
213            // slicing at 0 position would be useless
214            if (foundIndex <= 0)
215              foundIndex = message.lastIndexOf(QRegExp("\\s"));
216
217            if (foundIndex > 0)
218            {
219              message.truncate(foundIndex);
220              messageRaw = codec->fromUnicode(message);
221            }
222          }
223        }
224        else
225        {
226          messageRaw = codec->fromUnicode(s1);
227        }
228
229        icqEventTag = gLicqDaemon->ProtoSendMessage(
230            myId.toLatin1(), m_nPPID, messageRaw.data(), false, ICQ_TCPxMSG_NORMAL, true);
231
232        tmp = gTranslator.NToRN(messageRaw);
233        wholeMessagePos += strlen(tmp);
234        delete [] tmp;
235      }
236
237      break;
238    }
239    case ICQ_CMDxSUB_URL:
240    {
241      const ICQUser* u = gUserManager.FetchUser(myId.toLatin1(), m_nPPID, LOCK_R);
242      if (u == NULL) return;
243      grpSending->setTitle(tr("Sending mass URL to %1...").arg(QString::fromUtf8(u->GetAlias())));
244      QTextCodec* codec = UserCodec::codecForICQUser(u);
245      gUserManager.DropUser(u);
246
247      icqEventTag = gLicqDaemon->ProtoSendUrl(
248          myId.toLatin1(), m_nPPID, s2.toLatin1(),
249          codec->fromUnicode(s1), false, ICQ_TCPxMSG_NORMAL, true);
250      break;
251    }
252    case ICQ_CMDxSUB_CONTACTxLIST:
253    {
254      const ICQUser* u = gUserManager.FetchUser(myId.toLatin1(), m_nPPID, LOCK_R);
255      if (u == NULL) return;
256      grpSending->setTitle(tr("Sending mass list to %1...").arg(QString::fromUtf8(u->GetAlias())));
257      gUserManager.DropUser(u);
258
259      icqEventTag = gLicqDaemon->icqSendContactList(
260          myId.toLatin1(), *myUsers, false, ICQ_TCPxMSG_NORMAL);
261      break;
262    }
263  }
264
265  if (icqEventTag == 0) slot_done(NULL);
266}
267
268MMSendDlg::~MMSendDlg()
269{
270  if (icqEventTag != 0)
271  {
272    gLicqDaemon->CancelEvent(icqEventTag);
273    icqEventTag = 0;
274  }
275}
276
277void MMSendDlg::slot_cancel()
278{
279  if (icqEventTag != 0)
280  {
281    gLicqDaemon->CancelEvent(icqEventTag);
282    icqEventTag = 0;
283  }
284  //disconnect(sigman, SIGNAL(doneUserFcn(ICQEvent*)), SLOT(slot_done(ICQEvent*)));
285
286  reject();
287}
Note: See TracBrowser for help on using the browser.