root/trunk/qt4-gui/src/userevents/usersendmsgevent.cpp

Revision 6463, 6.3 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.

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 "usersendmsgevent.h"
22
23#include <QAction>
24#include <QActionGroup>
25#include <QSplitter>
26#include <QTextCodec>
27#include <QTimer>
28#include <QVBoxLayout>
29
30#include <licq_icqd.h>
31#include <licq_translate.h>
32
33#include "config/chat.h"
34
35#include "core/gui-defines.h"
36#include "core/licqgui.h"
37#include "core/messagebox.h"
38
39#include "dialogs/mmsenddlg.h"
40#include "dialogs/showawaymsgdlg.h"
41
42#include "widgets/mledit.h"
43
44#include "usereventcommon.h"
45#include "usereventtabdlg.h"
46
47using namespace LicqQtGui;
48/* TRANSLATOR LicqQtGui::UserSendMsgEvent */
49
50UserSendMsgEvent::UserSendMsgEvent(QString id, unsigned long ppid, QWidget* parent)
51  : UserSendCommon(MessageEvent, id, ppid, parent, "UserSendMsgEvent")
52{
53  myMainWidget->addWidget(myViewSplitter);
54  myMessageEdit->setFocus();
55  if (!Config::Chat::instance()->msgChatView())
56    myMessageEdit->setMinimumHeight(150);
57
58  myBaseTitle += tr(" - Message");
59
60  UserEventTabDlg* tabDlg = LicqGui::instance()->userEventTabDlg();
61  if (tabDlg != NULL && tabDlg->tabIsSelected(this))
62    tabDlg->setWindowTitle(myBaseTitle);
63
64  setWindowTitle(myBaseTitle);
65  myEventTypeGroup->actions().at(MessageEvent)->setChecked(true);
66}
67
68UserSendMsgEvent::~UserSendMsgEvent()
69{
70  // Empty
71}
72
73bool UserSendMsgEvent::sendDone(ICQEvent* /* e */)
74{
75  myMessageEdit->setText(QString::null);
76
77  bool showAwayDlg = false;
78  const ICQUser* u = gUserManager.FetchUser(myUsers.front().c_str(), myPpid, LOCK_R);
79  if (u != NULL)
80  {
81    showAwayDlg = u->Away() && u->ShowAwayMsg();
82    gUserManager.DropUser(u);
83  }
84
85  if (showAwayDlg && Config::Chat::instance()->popupAutoResponse())
86    new ShowAwayMsgDlg(myUsers.front().c_str(), myPpid);
87
88  return true;
89}
90
91void UserSendMsgEvent::resetSettings()
92{
93  myMessageEdit->clear();
94  myMessageEdit->setFocus();
95
96  // Makes the cursor blink so that the user sees that the text edit has focus.
97  myMessageEdit->moveCursor(QTextCursor::Start);
98
99  massMessageToggled(false);
100}
101
102void UserSendMsgEvent::send()
103{
104  // Take care of typing notification now
105  if (mySendTypingTimer->isActive())
106    mySendTypingTimer->stop();
107  connect(myMessageEdit, SIGNAL(textChanged()), SLOT(messageTextChanged()));
108  gLicqDaemon->ProtoTypingNotification(myUsers.front().c_str(), myPpid, false, myConvoId);
109
110  // do nothing if a command is already being processed
111  unsigned long icqEventTag = 0;
112  if (myEventTag.size())
113    icqEventTag = myEventTag.front();
114
115  if (icqEventTag != 0)
116    return;
117
118  if (!myMessageEdit->document()->isModified() &&
119      !QueryYesNo(this, tr("You didn't edit the message.\nDo you really want to send it?")))
120    return;
121
122  // don't let the user send empty messages
123  if (myMessageEdit->toPlainText().trimmed().isEmpty())
124    return;
125
126  if (!checkSecure())
127    return;
128
129  const ICQUser* u = gUserManager.FetchUser(myUsers.front().c_str(), myPpid, LOCK_R);
130  bool userOffline = true;
131  if (u != NULL)
132  {
133    userOffline = u->StatusOffline();
134    gUserManager.DropUser(u);
135  }
136
137  // create initial strings (implicit copying, no allocation impact :)
138  char* tmp = gTranslator.NToRN(myCodec->fromUnicode(myMessageEdit->toPlainText()));
139  QByteArray wholeMessageRaw(tmp);
140  delete [] tmp;
141  int wholeMessagePos = 0;
142
143  bool needsSplitting = false;
144  // If we send through server (= have message limit), and we've crossed the limit
145  unsigned short maxSize = userOffline ? MAX_OFFLINE_MESSAGE_SIZE : MAX_MESSAGE_SIZE;
146  if (mySendServerCheck->isChecked() && ((wholeMessageRaw.length() - wholeMessagePos) > maxSize))
147    needsSplitting = true;
148
149  QString message;
150  QByteArray messageRaw;
151
152  while (wholeMessageRaw.length() > wholeMessagePos)
153  {
154    if (needsSplitting)
155    {
156      // This is a bit ugly but adds safety. We don't simply search
157      // for a whitespace to cut at in the encoded text (since we don't
158      // really know how spaces are represented in its encoding), so
159      // we take the maximum length, then convert back to a Unicode string
160      // and then search for Unicode whitespaces.
161      messageRaw = wholeMessageRaw.mid(wholeMessagePos, maxSize);
162      tmp = gTranslator.RNToN(messageRaw);
163      messageRaw = tmp;
164      delete [] tmp;
165      message = myCodec->toUnicode(messageRaw);
166
167      if (wholeMessageRaw.length() - wholeMessagePos > maxSize)
168      {
169        // We try to find the optimal place to cut
170        // (according to our narrow-minded Latin1 idea of optimal :)
171        // prefer keeping sentences intact 1st
172        int foundIndex = message.lastIndexOf(QRegExp("[\\.\\n]"));
173        // slicing at 0 position would be useless
174        if (foundIndex <= 0)
175          foundIndex = message.lastIndexOf(QRegExp("\\s"));
176
177        if (foundIndex > 0)
178        {
179          message.truncate(foundIndex + 1);
180          messageRaw = myCodec->fromUnicode(message);
181        }
182      }
183    }
184    else
185    {
186      message = myMessageEdit->toPlainText();
187      messageRaw = myCodec->fromUnicode(message);
188    }
189
190    if (myMassMessageCheck->isChecked())
191    {
192      MMSendDlg* m = new MMSendDlg(myMassMessageList, this);
193      m->go_message(message);
194    }
195
196    icqEventTag = gLicqDaemon->ProtoSendMessage(
197        myUsers.front().c_str(),
198        myPpid,
199        messageRaw.data(),
200        mySendServerCheck->isChecked() ? false : true,
201        myUrgentCheck->isChecked() ? ICQ_TCPxMSG_URGENT : ICQ_TCPxMSG_NORMAL,
202        myMassMessageCheck->isChecked(),
203        &myIcqColor,
204        myConvoId);
205    if (myPpid == LICQ_PPID)
206      myEventTag.push_back(icqEventTag);
207
208    tmp = gTranslator.NToRN(messageRaw);
209    wholeMessagePos += strlen(tmp);
210    delete [] tmp;
211  }
212
213  UserSendCommon::send();
214}
Note: See TracBrowser for help on using the browser.