1 /*
2 This file is part of Choqok, the KDE micro-blogging client
3
4 Copyright (C) 2008-2012 Mehrdad Momeny <mehrdad.momeny@gmail.com>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, see http://www.gnu.org/licenses/
21 */
22 #include "composerwidget.h"
23
24 #include <QGridLayout>
25 #include <QLabel>
26 #include <QPointer>
27 #include <QPushButton>
28
29 #include "account.h"
30 #include "choqoktextedit.h"
31 #include "libchoqokdebug.h"
32 #include "microblog.h"
33 #include "notifymanager.h"
34 #include "shortenmanager.h"
35
36 namespace Choqok
37 {
38 namespace UI
39 {
40
41 class ComposerWidget::Private
42 {
43 public:
Private(Account * account)44 Private(Account *account)
45 : editor(nullptr), currentAccount(account), postToSubmit(nullptr)
46 {}
47 QPointer<TextEdit> editor;
48 Account *currentAccount;
49 Choqok::Post *postToSubmit;
50 QWidget *editorContainer;
51 QPointer<QLabel> replyToUsernameLabel;
52 QPointer<QPushButton> btnCancelReply;
53 };
54
ComposerWidget(Choqok::Account * account,QWidget * parent)55 ComposerWidget::ComposerWidget(Choqok::Account *account, QWidget *parent /*= 0*/)
56 : QWidget(parent), btnAbort(nullptr), d(new Private(account))
57 {
58 QVBoxLayout *layout = new QVBoxLayout(this);
59 layout->setContentsMargins(0, 0, 0, 0);
60 d->editorContainer = new QWidget(this);
61 QGridLayout *internalLayout = new QGridLayout;
62 internalLayout->setContentsMargins(0, 0, 0, 0);
63 d->editorContainer->setLayout(internalLayout);
64 layout->addWidget(editorContainer());
65 setEditor(new TextEdit(account->postCharLimit(), this));
66
67 d->replyToUsernameLabel = new QLabel(editorContainer());
68 d->btnCancelReply = new QPushButton(editorContainer());
69 d->btnCancelReply->setIcon(QIcon::fromTheme(QLatin1String("dialog-cancel")));
70 d->btnCancelReply->setToolTip(i18n("Discard Reply"));
71 d->btnCancelReply->setMaximumWidth(d->btnCancelReply->height());
72 connect(d->btnCancelReply, &QPushButton::clicked, this, &ComposerWidget::editorCleared);
73 internalLayout->addWidget(d->replyToUsernameLabel, 2, 0);
74 internalLayout->addWidget(d->btnCancelReply, 2, 1);
75
76 d->btnCancelReply->hide();
77 d->replyToUsernameLabel->hide();
78 }
79
~ComposerWidget()80 ComposerWidget::~ComposerWidget()
81 {
82 delete d;
83 }
84
setEditor(TextEdit * editor)85 void ComposerWidget::setEditor(TextEdit *editor)
86 {
87 qCDebug(CHOQOK);
88 if (d->editor) {
89 d->editor->deleteLater();
90 }
91 d->editor = editor;
92 qCDebug(CHOQOK);
93 if (d->editor) {
94 QGridLayout *internalLayout = qobject_cast<QGridLayout *>(d->editorContainer->layout());
95 internalLayout->addWidget(d->editor, 0, 0);
96 connect(d->editor, &TextEdit::returnPressed, this, &ComposerWidget::submitPost);
97 connect(d->editor, &TextEdit::textChanged, this, &ComposerWidget::editorTextChanged);
98 connect(d->editor, &TextEdit::cleared, this, &ComposerWidget::editorCleared);
99 editorTextChanged();
100 } else {
101 qCDebug(CHOQOK) << "Editor is NULL!";
102 }
103 }
104
setText(const QString & text,const QString & replyToId,const QString & replyToUsername)105 void ComposerWidget::setText(const QString &text, const QString &replyToId, const QString &replyToUsername)
106 {
107 d->editor->prependText(text);
108 this->replyToId = replyToId;
109 this->replyToUsername = replyToUsername;
110 if (!replyToUsername.isEmpty()) {
111 d->replyToUsernameLabel->setText(i18n("Replying to <b>%1</b>", replyToUsername));
112 d->btnCancelReply->show();
113 d->replyToUsernameLabel->show();
114 }
115 d->editor->setFocus();
116 }
117
submitPost(const QString & txt)118 void ComposerWidget::submitPost(const QString &txt)
119 {
120 qCDebug(CHOQOK);
121 editorContainer()->setEnabled(false);
122 QString text = txt;
123 if (currentAccount()->postCharLimit() &&
124 text.size() > (int)currentAccount()->postCharLimit()) {
125 text = Choqok::ShortenManager::self()->parseText(text);
126 }
127 delete d->postToSubmit;
128 d->postToSubmit = new Choqok::Post;
129 d->postToSubmit->content = text;
130 if (!replyToId.isEmpty()) {
131 d->postToSubmit->replyToPostId = replyToId;
132 }
133 connect(d->currentAccount->microblog(), &MicroBlog::postCreated,
134 this, &ComposerWidget::slotPostSubmited);
135 connect(d->currentAccount->microblog(), &MicroBlog::errorPost,
136 this, &ComposerWidget::slotErrorPost);
137 btnAbort = new QPushButton(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("Abort"), this);
138 layout()->addWidget(btnAbort);
139 connect(btnAbort, &QPushButton::clicked, this, &ComposerWidget::abort);
140 currentAccount()->microblog()->createPost(currentAccount(), d->postToSubmit);
141 }
142
slotPostSubmited(Choqok::Account * theAccount,Choqok::Post * post)143 void ComposerWidget::slotPostSubmited(Choqok::Account *theAccount, Choqok::Post *post)
144 {
145 qCDebug(CHOQOK);
146 if (currentAccount() == theAccount && post == d->postToSubmit) {
147 qCDebug(CHOQOK) << "Accepted";
148 disconnect(d->currentAccount->microblog(), &MicroBlog::postCreated,
149 this, &ComposerWidget::slotPostSubmited);
150 disconnect(d->currentAccount->microblog(), &MicroBlog::errorPost,
151 this, &ComposerWidget::slotErrorPost);
152 if (btnAbort) {
153 btnAbort->deleteLater();
154 }
155 d->editor->clear();
156 editorCleared();
157 editorContainer()->setEnabled(true);
158 delete d->postToSubmit;
159 d->postToSubmit = nullptr;
160 currentAccount()->microblog()->updateTimelines(currentAccount());
161 }
162 }
163
slotErrorPost(Account * theAccount,Post * post)164 void ComposerWidget::slotErrorPost(Account *theAccount, Post *post)
165 {
166 qCDebug(CHOQOK);
167 if (theAccount == d->currentAccount && post == d->postToSubmit) {
168 qCDebug(CHOQOK);
169 disconnect(d->currentAccount->microblog(), &MicroBlog::postCreated,
170 this, &ComposerWidget::slotPostSubmited);
171 disconnect(d->currentAccount->microblog(), &MicroBlog::errorPost,
172 this, &ComposerWidget::slotErrorPost);
173 if (btnAbort) {
174 btnAbort->deleteLater();
175 }
176 editorContainer()->setEnabled(true);
177 editor()->setFocus();
178 }
179 }
180
editorTextChanged()181 void ComposerWidget::editorTextChanged()
182 {
183 if (d->editor->toPlainText().length()) {
184 d->editor->setMaximumHeight(qMax(d->editor->fontMetrics().height() * 3,
185 80));
186 d->editor->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
187 } else {
188 d->editor->setMaximumHeight(qMax(d->editor->fontMetrics().height(),
189 30));
190 d->editor->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
191 }
192 }
193
editor()194 TextEdit *ComposerWidget::editor()
195 {
196 return d->editor;
197 }
198
editorContainer()199 QWidget *ComposerWidget::editorContainer()
200 {
201 return d->editorContainer;
202 }
203
postToSubmit()204 Post *ComposerWidget::postToSubmit()
205 {
206 return d->postToSubmit;
207 }
208
setPostToSubmit(Post * post)209 void ComposerWidget::setPostToSubmit(Post *post)
210 {
211 delete d->postToSubmit;
212 d->postToSubmit = post;
213 }
214
btnCancelReply()215 QPointer< QPushButton > ComposerWidget::btnCancelReply()
216 {
217 return d->btnCancelReply;
218 }
219
currentAccount()220 Account *ComposerWidget::currentAccount()
221 {
222 return d->currentAccount;
223 }
224
replyToUsernameLabel()225 QPointer< QLabel > ComposerWidget::replyToUsernameLabel()
226 {
227 return d->replyToUsernameLabel;
228 }
229
editorCleared()230 void ComposerWidget::editorCleared()
231 {
232 replyToId.clear();
233 replyToUsername.clear();
234 d->btnCancelReply->hide();
235 d->replyToUsernameLabel->hide();
236 }
237
abort()238 void ComposerWidget::abort()
239 {
240 if (btnAbort) {
241 btnAbort->deleteLater();
242 }
243 editorContainer()->setEnabled(true);
244 currentAccount()->microblog()->abortCreatePost(currentAccount(), d->postToSubmit);
245 editor()->setFocus();
246 }
247
248 }
249 }
250