File indexing completed on 2024-04-28 04:55:37
0001 /* 0002 This file is part of Choqok, the KDE micro-blogging client 0003 0004 SPDX-FileCopyrightText: 2008-2012 Mehrdad Momeny <mehrdad.momeny@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "twitterapimicroblogwidget.h" 0010 0011 #include <QAction> 0012 #include <QFont> 0013 #include <QIcon> 0014 #include <QMenu> 0015 #include <QPainter> 0016 #include <QRect> 0017 #include <QToolButton> 0018 0019 #include <KLocalizedString> 0020 0021 #include "account.h" 0022 #include "composerwidget.h" 0023 0024 #include "twitterapiaccount.h" 0025 #include "twitterapidebug.h" 0026 #include "twitterapimicroblog.h" 0027 #include "twitterapisearchtimelinewidget.h" 0028 0029 class TwitterApiMicroBlogWidget::Private 0030 { 0031 public: 0032 Private(Choqok::Account *acc) 0033 : btnCloseSearch(nullptr) 0034 { 0035 qCDebug(CHOQOK); 0036 mBlog = qobject_cast<TwitterApiMicroBlog *>(acc->microblog()); 0037 this->account = qobject_cast<TwitterApiAccount *>(acc); 0038 } 0039 TwitterApiMicroBlog *mBlog; 0040 TwitterApiAccount *account; 0041 QToolButton *btnCloseSearch; 0042 }; 0043 0044 QIcon addTextToIcon(const QIcon &icon, const QString &text, const QSize &result_size , const QPalette &palette) 0045 { 0046 QIcon result; 0047 0048 QPixmap pixmap = icon.pixmap(result_size); 0049 QPainter painter(&pixmap); 0050 QFont font; 0051 font.setWeight(result_size.height() / 3); 0052 font.setBold(true); 0053 painter.setFont(font); 0054 0055 int textWidth = painter.fontMetrics().horizontalAdvance(text); 0056 QRect rct(0 , 0 , textWidth , result_size.height() / 2); 0057 0058 painter.setRenderHint(QPainter::Antialiasing); 0059 painter.setPen(palette.color(QPalette::Active , QPalette::HighlightedText)); 0060 painter.drawText(rct , Qt::AlignTop | Qt::AlignLeft , text); 0061 0062 result.addPixmap(pixmap , QIcon::Active); 0063 0064 return result; 0065 } 0066 0067 TwitterApiMicroBlogWidget::TwitterApiMicroBlogWidget(Choqok::Account *account, QWidget *parent) 0068 : MicroBlogWidget(account, parent), d(new Private(account)) 0069 { 0070 qCDebug(CHOQOK); 0071 connect(account, &Choqok::Account::modified, this, &TwitterApiMicroBlogWidget::slotAccountModified); 0072 connect(d->mBlog->searchBackend(), &TwitterApiSearch::searchResultsReceived, 0073 this, &TwitterApiMicroBlogWidget::slotSearchResultsReceived); 0074 connect(d->mBlog, &TwitterApiMicroBlog::saveTimelines, this, 0075 &TwitterApiMicroBlogWidget::saveSearchTimelinesState); 0076 loadSearchTimelinesState(); 0077 } 0078 0079 void TwitterApiMicroBlogWidget::initUi() 0080 { 0081 qCDebug(CHOQOK); 0082 Choqok::UI::MicroBlogWidget::initUi(); 0083 connect(timelinesTabWidget(), (void (Choqok::UI::ChoqokTabBar::*)(QWidget*,const QPoint&))&Choqok::UI::ChoqokTabBar::contextMenu, 0084 this, &TwitterApiMicroBlogWidget::slotContextMenu); 0085 // connect(timelinesTabWidget(), SIGNAL(currentChanged(int)), SLOT(slotCurrentTimelineChanged(int)) ); 0086 // d->btnCloseSearch->setIcon(QIcon::fromTheme("tab-close")); 0087 // d->btnCloseSearch->setAutoRaise(true); 0088 // d->btnCloseSearch->setToolTip(i18nc("Close a timeline", "Close Timeline")); 0089 // d->btnCloseSearch->setFixedWidth( 32 ); 0090 // timelinesTabWidget()->setTabAlongsideWidget( d->btnCloseSearch ); 0091 0092 // connect(d->btnCloseSearch, SIGNAL(clicked(bool)), SLOT(slotCloseCurrentSearch()) ); 0093 // slotCurrentTimelineChanged(timelinesTabWidget()->currentIndex()); 0094 } 0095 0096 TwitterApiMicroBlogWidget::~TwitterApiMicroBlogWidget() 0097 { 0098 delete d; 0099 } 0100 0101 void TwitterApiMicroBlogWidget::slotSearchResultsReceived(const SearchInfo &info, 0102 QList< Choqok::Post * > &postsList) 0103 { 0104 qCDebug(CHOQOK); 0105 if (info.account == currentAccount()) { 0106 qCDebug(CHOQOK) << postsList.count(); 0107 QString name = QStringLiteral("%1%2").arg(d->mBlog->searchBackend()->optionCode(info.option)).arg(info.query); 0108 if (mSearchTimelines.contains(name)) { 0109 mSearchTimelines.value(name)->addNewPosts(postsList); 0110 } else { 0111 if (postsList.isEmpty()) { 0112 addSearchTimelineWidgetToUi(name, info)->addPlaceholderMessage(i18n("(The search result is empty.)")); 0113 } else { 0114 addSearchTimelineWidgetToUi(name, info)->addNewPosts(postsList); 0115 } 0116 } 0117 } 0118 } 0119 0120 TwitterApiSearchTimelineWidget *TwitterApiMicroBlogWidget::addSearchTimelineWidgetToUi(const QString &name, 0121 const SearchInfo &info) 0122 { 0123 qCDebug(CHOQOK); 0124 TwitterApiSearchTimelineWidget *mbw = d->mBlog->createSearchTimelineWidget(currentAccount(), name, 0125 info, this); 0126 if (mbw) { 0127 mbw->setObjectName(name); 0128 mSearchTimelines.insert(name, mbw); 0129 timelines().insert(name, mbw); 0130 timelinesTabWidget()->addTab(mbw, name); 0131 QString textToAdd = name; 0132 if (textToAdd.contains(QLatin1Char(':'))) { 0133 QStringList splitted = textToAdd.split(QLatin1Char(':')); 0134 textToAdd = splitted.first().at(0) + QLatin1Char(':') + splitted[1].left(3); 0135 } else { 0136 textToAdd = textToAdd.left(4); 0137 } 0138 QIcon icon = addTextToIcon(QIcon::fromTheme(QLatin1String("edit-find")), textToAdd, QSize(40, 40), palette()); 0139 mbw->setTimelineIcon(icon); 0140 timelinesTabWidget()->setTabIcon(timelinesTabWidget()->indexOf(mbw), icon); 0141 connect(mbw, SIGNAL(updateUnreadCount(int)), this, SLOT(slotUpdateUnreadCount(int))); 0142 connect(mbw, &TwitterApiSearchTimelineWidget::closeMe, this, &TwitterApiMicroBlogWidget::slotCloseCurrentSearch); 0143 if (composer()) { 0144 connect(mbw, SIGNAL(forwardResendPost(QString)), composer(), SLOT(setText(QString))); 0145 connect(mbw, &TwitterApiSearchTimelineWidget::forwardReply, composer(), &Choqok::UI::ComposerWidget::setText); 0146 } 0147 timelinesTabWidget()->setCurrentWidget(mbw); 0148 } else { 0149 qCDebug(CHOQOK) << "Cannot Create a new TimelineWidget for timeline " << name; 0150 return nullptr; 0151 } 0152 if (timelinesTabWidget()->count() == 1) { 0153 timelinesTabWidget()->setTabBarHidden(true); 0154 } else { 0155 timelinesTabWidget()->setTabBarHidden(false); 0156 } 0157 return mbw; 0158 } 0159 0160 void TwitterApiMicroBlogWidget::slotCloseCurrentSearch() 0161 { 0162 Choqok::UI::TimelineWidget *stw = qobject_cast<Choqok::UI::TimelineWidget *>(sender()); 0163 if (!stw) { 0164 stw = qobject_cast<Choqok::UI::TimelineWidget *>(timelinesTabWidget()->currentWidget()); 0165 } 0166 closeSearch(stw); 0167 } 0168 0169 void TwitterApiMicroBlogWidget::slotAccountModified(Choqok::Account *account) 0170 { 0171 for (const QString &timeline: account->microblog()->timelineNames()) { 0172 if (account->timelineNames().contains(timeline)) { 0173 if (!timelines().contains(timeline)) { 0174 addTimelineWidgetToUi(timeline); 0175 } 0176 } else if (timelines().contains(timeline)) { 0177 Choqok::UI::TimelineWidget *tm = timelines().take(timeline); 0178 tm->deleteLater(); 0179 } 0180 } 0181 } 0182 0183 void TwitterApiMicroBlogWidget::saveSearchTimelinesState() 0184 { 0185 qCDebug(CHOQOK); 0186 int count = currentAccount()->configGroup()->readEntry("SearchCount", 0); 0187 int i = 0; 0188 while (i < count) { 0189 currentAccount()->configGroup()->deleteEntry(QLatin1String("Search") + QString::number(i)); 0190 ++i; 0191 } 0192 i = 0; 0193 for (TwitterApiSearchTimelineWidget *tm: mSearchTimelines.values()) { 0194 currentAccount()->configGroup()->writeEntry(QLatin1String("Search") + QString::number(i), tm->searchInfo().toString()); 0195 ++i; 0196 } 0197 currentAccount()->configGroup()->writeEntry("SearchCount", i); 0198 } 0199 0200 void TwitterApiMicroBlogWidget::loadSearchTimelinesState() 0201 { 0202 qCDebug(CHOQOK); 0203 int count = currentAccount()->configGroup()->readEntry(QLatin1String("SearchCount"), 0); 0204 int i = 0; 0205 while (i < count) { 0206 SearchInfo info; 0207 if (info.fromString(currentAccount()->configGroup()->readEntry(QLatin1String("Search") + QString::number(i), QString()))) { 0208 qobject_cast<TwitterApiMicroBlog *>(currentAccount()->microblog())->searchBackend()->requestSearchResults(info); 0209 } 0210 ++i; 0211 } 0212 } 0213 0214 void TwitterApiMicroBlogWidget::slotContextMenu(QWidget *w, const QPoint &pt) 0215 { 0216 qCDebug(CHOQOK); 0217 Choqok::UI::TimelineWidget *sWidget = qobject_cast<Choqok::UI::TimelineWidget *>(w); 0218 QMenu menu; 0219 QAction *mar = nullptr; 0220 QAction *ac = nullptr; 0221 if (sWidget->unreadCount() > 0) { 0222 mar = new QAction(QIcon::fromTheme(QLatin1String("mail-mark-read")), i18n("Mark timeline as read"), &menu); 0223 menu.addAction(mar); 0224 } 0225 if (sWidget->isClosable()) { 0226 ac = new QAction(QIcon::fromTheme(QLatin1String("tab-close")), i18n("Close Timeline"), &menu); 0227 QAction *closeAll = new QAction(QIcon::fromTheme(QLatin1String("tab-close")), i18n("Close All"), &menu); 0228 connect(closeAll, &QAction::triggered, this, &TwitterApiMicroBlogWidget::closeAllSearches); 0229 menu.addAction(ac); 0230 menu.addAction(closeAll); 0231 } 0232 QAction *res = menu.exec(pt); 0233 if (ac && res == ac) { 0234 closeSearch(sWidget); 0235 } else if (res == mar) { 0236 sWidget->markAllAsRead(); 0237 } 0238 } 0239 0240 void TwitterApiMicroBlogWidget::closeSearch(Choqok::UI::TimelineWidget *searchWidget) 0241 { 0242 if (!searchWidget) { 0243 return; 0244 } 0245 searchWidget->markAllAsRead(); 0246 TwitterApiSearchTimelineWidget *tst = qobject_cast<TwitterApiSearchTimelineWidget *>(searchWidget); 0247 timelinesTabWidget()->removePage(searchWidget); 0248 if (tst) { 0249 QString name = mSearchTimelines.key(tst); 0250 mSearchTimelines.value(name)->close(); 0251 mSearchTimelines.remove(name); 0252 timelines().remove(name); 0253 } else { 0254 QStringList lst = d->account->timelineNames(); 0255 lst.removeOne(searchWidget->timelineName()); 0256 d->account->setTimelineNames(lst); 0257 d->account->writeConfig(); 0258 timelines().remove(timelines().key(searchWidget)); 0259 searchWidget->close(); 0260 } 0261 } 0262 0263 void TwitterApiMicroBlogWidget::closeAllSearches() 0264 { 0265 for (TwitterApiSearchTimelineWidget *searchWidget: mSearchTimelines.values()) { 0266 closeSearch(searchWidget); 0267 } 0268 for (Choqok::UI::TimelineWidget *widget: timelines().values()) { 0269 if (widget->isClosable()) { 0270 closeSearch(widget); 0271 } 0272 } 0273 } 0274 0275 #include "moc_twitterapimicroblogwidget.cpp"