1 /* ============================================================
2 * QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
3 * Copyright (C) 2011-2020 QuiteRSS Team <quiterssteam@gmail.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 * ============================================================ */
18 #include "newstabwidget.h"
19 
20 #include "mainapplication.h"
21 #include "adblockicon.h"
22 #include "settings.h"
23 #include "webpage.h"
24 
25 #if defined(Q_OS_WIN)
26 #include <qt_windows.h>
27 #endif
28 #include <qzregexp.h>
29 
NewsTabWidget(QWidget * parent,TabType type,int feedId,int feedParId)30 NewsTabWidget::NewsTabWidget(QWidget *parent, TabType type, int feedId, int feedParId)
31   : QWidget(parent)
32   , type_(type)
33   , feedId_(feedId)
34   , feedParId_(feedParId)
35   , currentNewsIdOld(-1)
36   , autoLoadImages_(true)
37 {
38   mainWindow_ = mainApp->mainWindow();
39   db_ = QSqlDatabase::database();
40   feedsView_ = mainWindow_->feedsView_;
41   feedsModel_ = mainWindow_->feedsModel_;
42   feedsProxyModel_ = mainWindow_->feedsProxyModel_;
43 
44   newsIconTitle_ = new QLabel();
45   newsIconMovie_ = new QMovie(":/images/loading");
46   newsIconTitle_->setMovie(newsIconMovie_);
47   newsTextTitle_ = new QLabel();
48   newsTextTitle_->setObjectName("newsTextTitle_");
49 
50   closeButton_ = new QToolButton();
51   closeButton_->setFixedSize(15, 15);
52   closeButton_->setCursor(Qt::ArrowCursor);
53   closeButton_->setStyleSheet(
54         "QToolButton { background-color: transparent;"
55         "border: none; padding: 0px;"
56         "image: url(:/images/close); }"
57         "QToolButton:hover {"
58         "image: url(:/images/closeHover); }"
59         );
60   connect(closeButton_, SIGNAL(clicked()),
61           this, SLOT(slotTabClose()));
62 
63   QHBoxLayout *newsTitleLayout = new QHBoxLayout();
64   newsTitleLayout->setMargin(0);
65   newsTitleLayout->setSpacing(0);
66   newsTitleLayout->addWidget(newsIconTitle_);
67   newsTitleLayout->addSpacing(3);
68   newsTitleLayout->addWidget(newsTextTitle_, 1);
69   newsTitleLayout->addWidget(closeButton_);
70 
71   newsTitleLabel_ = new QWidget();
72   newsTitleLabel_->setObjectName("newsTitleLabel_");
73   newsTitleLabel_->setMinimumHeight(16);
74   newsTitleLabel_->setLayout(newsTitleLayout);
75   newsTitleLabel_->setVisible(false);
76 
77   Settings settings;
78   bool showCloseButtonTab = settings.value("Settings/showCloseButtonTab", true).toBool();
79   if (!showCloseButtonTab) {
80     closeButton_->hide();
81     newsTitleLabel_->setFixedWidth(MAX_TAB_WIDTH-15);
82   } else {
83     newsTitleLabel_->setFixedWidth(MAX_TAB_WIDTH);
84   }
85 
86   if (type_ != TabTypeDownloads) {
87     if (type_ != TabTypeWeb) {
88       createNewsList();
89     } else {
90       autoLoadImages_ = mainWindow_->autoLoadImages_;
91     }
92     createWebWidget();
93 
94     if (type_ != TabTypeWeb) {
95       newsTabWidgetSplitter_ = new QSplitter(this);
96       newsTabWidgetSplitter_->setObjectName("newsTabWidgetSplitter");
97 
98       if ((mainWindow_->browserPosition_ == TOP_POSITION) ||
99           (mainWindow_->browserPosition_ == LEFT_POSITION)) {
100         newsTabWidgetSplitter_->addWidget(webWidget_);
101         newsTabWidgetSplitter_->addWidget(newsWidget_);
102       } else {
103         newsTabWidgetSplitter_->addWidget(newsWidget_);
104         newsTabWidgetSplitter_->addWidget(webWidget_);
105       }
106     }
107   }
108 
109   QVBoxLayout *layout = new QVBoxLayout();
110   layout->setMargin(0);
111   layout->setSpacing(0);
112   if (type_ == TabTypeDownloads)
113     layout->addWidget(mainApp->downloadManager());
114   else if (type_ != TabTypeWeb)
115     layout->addWidget(newsTabWidgetSplitter_);
116   else
117     layout->addWidget(webWidget_);
118   setLayout(layout);
119 
120   if (type_ < TabTypeWeb) {
121     newsTabWidgetSplitter_->setHandleWidth(1);
122 
123     if ((mainWindow_->browserPosition_ == RIGHT_POSITION) ||
124         (mainWindow_->browserPosition_ == LEFT_POSITION)) {
125       newsTabWidgetSplitter_->setOrientation(Qt::Horizontal);
126       newsTabWidgetSplitter_->setStyleSheet(
127             QString("QSplitter::handle {background: qlineargradient("
128                     "x1: 0, y1: 0, x2: 0, y2: 1,"
129                     "stop: 0 %1, stop: 0.07 %2);}").
130             arg(newsPanelWidget_->palette().background().color().name()).
131             arg(qApp->palette().color(QPalette::Dark).name()));
132     } else {
133       newsTabWidgetSplitter_->setOrientation(Qt::Vertical);
134       newsTabWidgetSplitter_->setStyleSheet(
135             QString("QSplitter::handle {background: %1; margin-top: 1px; margin-bottom: 1px;}").
136             arg(qApp->palette().color(QPalette::Dark).name()));
137     }
138   }
139 
140   connect(this, SIGNAL(signalSetTextTab(QString,NewsTabWidget*)),
141           mainWindow_, SLOT(setTextTitle(QString,NewsTabWidget*)));
142 }
143 
~NewsTabWidget()144 NewsTabWidget::~NewsTabWidget()
145 {
146   if (type_ == TabTypeDownloads) {
147     mainApp->downloadManager()->hide();
148     mainApp->downloadManager()->setParent(mainWindow_);
149   }
150 }
151 
disconnectObjects()152 void NewsTabWidget::disconnectObjects()
153 {
154   disconnect(this);
155   if (type_ != TabTypeDownloads) {
156     webView_->disconnect(this);
157     webView_->disconnectObjects();
158     qobject_cast<WebPage*>(webView_->page())->disconnectObjects();
159   }
160 }
161 
162 /** @brief Create news list with all related panels
163  *----------------------------------------------------------------------------*/
createNewsList()164 void NewsTabWidget::createNewsList()
165 {
166   newsView_ = new NewsView(this);
167   newsView_->setFrameStyle(QFrame::NoFrame);
168   newsModel_ = new NewsModel(this, newsView_);
169   newsModel_->setTable("news");
170   newsModel_->setFilter("feedId=-1");
171   newsHeader_ = new NewsHeader(newsModel_, newsView_);
172 
173   newsView_->setModel(newsModel_);
174   newsView_->setHeader(newsHeader_);
175 
176   newsHeader_->init();
177 
178   newsToolBar_ = new QToolBar(this);
179   newsToolBar_->setObjectName("newsToolBar");
180   newsToolBar_->setStyleSheet("QToolBar { border: none; padding: 0px; }");
181 
182   Settings settings;
183   QString actionListStr = "markNewsRead,markAllNewsRead,Separator,markStarAct,"
184                           "newsLabelAction,shareMenuAct,openInExternalBrowserAct,Separator,"
185                           "nextUnreadNewsAct,prevUnreadNewsAct,Separator,"
186                           "newsFilter,Separator,deleteNewsAct";
187   QString str = settings.value("Settings/newsToolBar", actionListStr).toString();
188 
189   foreach (QString actionStr, str.split(",", QString::SkipEmptyParts)) {
190     if (actionStr == "Separator") {
191       newsToolBar_->addSeparator();
192     } else {
193       QListIterator<QAction *> iter(mainWindow_->actions());
194       while (iter.hasNext()) {
195         QAction *pAction = iter.next();
196         if (!pAction->icon().isNull()) {
197           if (pAction->objectName() == actionStr) {
198             newsToolBar_->addAction(pAction);
199             break;
200           }
201         }
202       }
203     }
204   }
205   separatorRAct_ = newsToolBar_->addSeparator();
206   separatorRAct_->setObjectName("separatorRAct");
207   newsToolBar_->addAction(mainWindow_->restoreNewsAct_);
208 
209   findText_ = new FindTextContent(this);
210   findText_->setFixedWidth(200);
211 
212   QHBoxLayout *newsPanelLayout = new QHBoxLayout();
213   newsPanelLayout->setMargin(2);
214   newsPanelLayout->setSpacing(2);
215   newsPanelLayout->addWidget(newsToolBar_);
216   newsPanelLayout->addStretch(1);
217   newsPanelLayout->addWidget(findText_);
218 
219   newsPanelWidget_ = new QWidget(this);
220   newsPanelWidget_->setObjectName("newsPanelWidget_");
221   newsPanelWidget_->setStyleSheet(
222         QString("#newsPanelWidget_ {border-bottom: 1px solid %1;}").
223         arg(qApp->palette().color(QPalette::Dark).name()));
224 
225   newsPanelWidget_->setLayout(newsPanelLayout);
226   if (!mainWindow_->newsToolbarToggle_->isChecked())
227     newsPanelWidget_->hide();
228 
229   QVBoxLayout *newsLayout = new QVBoxLayout();
230   newsLayout->setMargin(0);
231   newsLayout->setSpacing(0);
232   newsLayout->addWidget(newsPanelWidget_);
233   newsLayout->addWidget(newsView_);
234 
235   newsWidget_ = new QWidget(this);
236   newsWidget_->setLayout(newsLayout);
237 
238   markNewsReadTimer_ = new QTimer(this);
239 
240   QFile htmlFile;
241   htmlFile.setFileName(":/html/newspaper_head");
242   htmlFile.open(QFile::ReadOnly);
243   newspaperHeadHtml_ = QString::fromUtf8(htmlFile.readAll());
244   htmlFile.close();
245   htmlFile.setFileName(":/html/newspaper_description");
246   htmlFile.open(QFile::ReadOnly);
247   newspaperHtml_ = QString::fromUtf8(htmlFile.readAll());
248   htmlFile.close();
249   htmlFile.setFileName(":/html/newspaper_description_rtl");
250   htmlFile.open(QFile::ReadOnly);
251   newspaperHtmlRtl_ = QString::fromUtf8(htmlFile.readAll());
252   htmlFile.close();
253   htmlFile.setFileName(":/html/description");
254   htmlFile.open(QFile::ReadOnly);
255   htmlString_ = QString::fromUtf8(htmlFile.readAll());
256   htmlFile.close();
257   htmlFile.setFileName(":/html/description_rtl");
258   htmlFile.open(QFile::ReadOnly);
259   htmlRtlString_ = QString::fromUtf8(htmlFile.readAll());
260   htmlFile.close();
261 
262   connect(newsView_, SIGNAL(pressed(QModelIndex)),
263           this, SLOT(slotNewsViewClicked(QModelIndex)));
264   connect(newsView_, SIGNAL(pressKeyUp(QModelIndex)),
265           this, SLOT(slotNewsUpPressed(QModelIndex)));
266   connect(newsView_, SIGNAL(pressKeyDown(QModelIndex)),
267           this, SLOT(slotNewsDownPressed(QModelIndex)));
268   connect(newsView_, SIGNAL(pressKeyHome(QModelIndex)),
269           this, SLOT(slotNewsHomePressed(QModelIndex)));
270   connect(newsView_, SIGNAL(pressKeyEnd(QModelIndex)),
271           this, SLOT(slotNewsEndPressed(QModelIndex)));
272   connect(newsView_, SIGNAL(pressKeyPageUp(QModelIndex)),
273           this, SLOT(slotNewsPageUpPressed(QModelIndex)));
274   connect(newsView_, SIGNAL(pressKeyPageDown(QModelIndex)),
275           this, SLOT(slotNewsPageDownPressed(QModelIndex)));
276   connect(newsView_, SIGNAL(signalSetItemRead(QModelIndex, int)),
277           this, SLOT(slotSetItemRead(QModelIndex, int)));
278   connect(newsView_, SIGNAL(signalSetItemStar(QModelIndex,int)),
279           this, SLOT(slotSetItemStar(QModelIndex,int)));
280   connect(newsView_, SIGNAL(signalDoubleClicked(QModelIndex)),
281           this, SLOT(slotNewsViewDoubleClicked(QModelIndex)));
282   connect(newsView_, SIGNAL(signalMiddleClicked(QModelIndex)),
283           this, SLOT(slotNewsMiddleClicked(QModelIndex)));
284   connect(newsView_, SIGNAL(signaNewslLabelClicked(QModelIndex)),
285           this, SLOT(slotNewslLabelClicked(QModelIndex)));
286   connect(markNewsReadTimer_, SIGNAL(timeout()),
287           this, SLOT(slotMarkReadTimeout()));
288   connect(newsView_, SIGNAL(customContextMenuRequested(QPoint)),
289           this, SLOT(showContextMenuNews(const QPoint &)));
290 
291   connect(newsModel_, SIGNAL(signalSort(int,int)),
292           this, SLOT(slotSort(int,int)));
293 
294   connect(findText_, SIGNAL(textChanged(QString)),
295           this, SLOT(slotFindText(QString)));
296   connect(findText_, SIGNAL(signalSelectFind()),
297           this, SLOT(slotSelectFind()));
298   connect(findText_, SIGNAL(returnPressed()),
299           this, SLOT(slotSelectFind()));
300   connect(findText_, SIGNAL(signalVisible(bool)),
301           mainWindow_, SLOT(findText()));
302 
303   connect(mainWindow_->newsToolbarToggle_, SIGNAL(toggled(bool)),
304           newsPanelWidget_, SLOT(setVisible(bool)));
305 }
306 
307 /** @brief Call context menu of selected news in news list
308  *----------------------------------------------------------------------------*/
showContextMenuNews(const QPoint & pos)309 void NewsTabWidget::showContextMenuNews(const QPoint &pos)
310 {
311   if (!newsView_->currentIndex().isValid()) return;
312 
313   QMenu menu;
314   menu.addAction(mainWindow_->restoreNewsAct_);
315   menu.addSeparator();
316   menu.addAction(mainWindow_->openInBrowserAct_);
317   menu.addAction(mainWindow_->openInExternalBrowserAct_);
318   menu.addAction(mainWindow_->openNewsNewTabAct_);
319   menu.addSeparator();
320   menu.addAction(mainWindow_->markNewsRead_);
321   menu.addAction(mainWindow_->markAllNewsRead_);
322   menu.addSeparator();
323   menu.addAction(mainWindow_->markStarAct_);
324   menu.addAction(mainWindow_->newsLabelMenuAction_);
325   menu.addAction(mainWindow_->shareMenuAct_);
326   menu.addAction(mainWindow_->copyLinkAct_);
327   menu.addSeparator();
328   menu.addAction(mainWindow_->updateFeedAct_);
329   menu.addSeparator();
330   menu.addAction(mainWindow_->deleteNewsAct_);
331   menu.addAction(mainWindow_->deleteAllNewsAct_);
332 
333   menu.exec(newsView_->viewport()->mapToGlobal(pos));
334 }
335 
336 /** @brief Create web-widget and control panel
337  *----------------------------------------------------------------------------*/
createWebWidget()338 void NewsTabWidget::createWebWidget()
339 {
340   webView_ = new WebView(this);
341 
342   webViewProgress_ = new QProgressBar(this);
343   webViewProgress_->setObjectName("webViewProgress_");
344   webViewProgress_->setFixedHeight(15);
345   webViewProgress_->setMinimum(0);
346   webViewProgress_->setMaximum(100);
347   webViewProgress_->setVisible(true);
348   connect(this, SIGNAL(loadProgress(int)),
349           webViewProgress_, SLOT(setValue(int)), Qt::QueuedConnection);
350 
351   webViewProgressLabel_ = new QLabel(this);
352   webViewProgressLabel_->setObjectName("webViewProgressLabel_");
353   webViewProgressLabel_->setStyleSheet("background: none;");
354   QHBoxLayout *progressLayout = new QHBoxLayout();
355   progressLayout->setMargin(0);
356   progressLayout->addWidget(webViewProgressLabel_, 0, Qt::AlignLeft|Qt::AlignVCenter);
357   webViewProgress_->setLayout(progressLayout);
358 
359   //! Create web control panel
360   webToolBar_ = new QToolBar(this);
361   webToolBar_->setStyleSheet("QToolBar { border: none; padding: 0px; }");
362   webToolBar_->setIconSize(QSize(18, 18));
363 
364   webHomePageAct_ = new QAction(this);
365   webHomePageAct_->setIcon(QIcon(":/images/homePage"));
366 
367   webToolBar_->addAction(webHomePageAct_);
368   QAction *webAction = webView_->pageAction(QWebPage::Back);
369   webToolBar_->addAction(webAction);
370   webAction = webView_->pageAction(QWebPage::Forward);
371   webToolBar_->addAction(webAction);
372   webAction = webView_->pageAction(QWebPage::Reload);
373   webToolBar_->addAction(webAction);
374   webAction = webView_->pageAction(QWebPage::Stop);
375   webToolBar_->addAction(webAction);
376   webToolBar_->addSeparator();
377 
378   webToolBar_->addAction(mainApp->mainWindow()->shareMenuAct_);
379 
380   webExternalBrowserAct_ = new QAction(this);
381   webExternalBrowserAct_->setIcon(QIcon(":/images/openBrowser"));
382   webToolBar_->addAction(webExternalBrowserAct_);
383 
384   locationBar_ = new LocationBar(webView_, this);
385 
386   QHBoxLayout *webControlPanelLayout = new QHBoxLayout();
387   webControlPanelLayout->setMargin(2);
388   webControlPanelLayout->setSpacing(2);
389   webControlPanelLayout->addWidget(webToolBar_);
390   webControlPanelLayout->addWidget(locationBar_, 1);
391 
392   webControlPanel_ = new QWidget(this);
393   webControlPanel_->setObjectName("webControlPanel_");
394   webControlPanel_->setStyleSheet(
395         QString("#webControlPanel_ {border-bottom: 1px solid %1;}").
396         arg(qApp->palette().color(QPalette::Dark).name()));
397   webControlPanel_->setLayout(webControlPanelLayout);
398 
399   if (type_ != TabTypeWeb)
400     setWebToolbarVisible(false, false);
401   else
402     setWebToolbarVisible(true, false);
403 
404   //! Create web layout
405   QVBoxLayout *webLayout = new QVBoxLayout();
406   webLayout->setMargin(0);
407   webLayout->setSpacing(0);
408   webLayout->addWidget(webControlPanel_);
409   webLayout->addWidget(webView_, 1);
410   webLayout->addWidget(webViewProgress_);
411 
412   webWidget_ = new QWidget(this);
413   webWidget_->setObjectName("webWidget_");
414   webWidget_->setLayout(webLayout);
415   webWidget_->setMinimumWidth(400);
416   webWidget_->setMinimumHeight(100);
417 
418   webView_->page()->action(QWebPage::OpenLink)->disconnect();
419   webView_->page()->action(QWebPage::OpenLinkInNewWindow)->disconnect();
420 
421   urlExternalBrowserAct_ = new QAction(this);
422   urlExternalBrowserAct_->setIcon(QIcon(":/images/openBrowser"));
423 
424   connect(webHomePageAct_, SIGNAL(triggered()),
425           this, SLOT(webHomePage()));
426   connect(webExternalBrowserAct_, SIGNAL(triggered()),
427           this, SLOT(openPageInExternalBrowser()));
428   connect(urlExternalBrowserAct_, SIGNAL(triggered()),
429           this, SLOT(openUrlInExternalBrowser()));
430   connect(this, SIGNAL(signalSetHtmlWebView(QString)),
431           SLOT(slotSetHtmlWebView(QString)), Qt::QueuedConnection);
432   connect(webView_, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted()));
433   connect(webView_, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool)));
434   connect(webView_, SIGNAL(linkClicked(QUrl)), this, SLOT(slotLinkClicked(QUrl)));
435   connect(webView_->page(), SIGNAL(linkHovered(QString,QString,QString)),
436           this, SLOT(slotLinkHovered(QString,QString,QString)));
437   connect(webView_, SIGNAL(loadProgress(int)), this, SLOT(slotSetValue(int)), Qt::QueuedConnection);
438 
439   connect(webView_, SIGNAL(titleChanged(QString)),
440           this, SLOT(webTitleChanged(QString)));
441   connect(webView_->page()->action(QWebPage::OpenLink), SIGNAL(triggered()),
442           this, SLOT(openLink()));
443   connect(webView_->page()->action(QWebPage::OpenLinkInNewWindow), SIGNAL(triggered()),
444           this, SLOT(openLinkInNewTab()));
445 
446   connect(webView_, SIGNAL(showContextMenu(QPoint)),
447           this, SLOT(showContextWebPage(QPoint)), Qt::QueuedConnection);
448   connect(webView_, SIGNAL(signalGoHome()),
449           this, SLOT(webHomePage()));
450 
451   connect(mainWindow_->autoLoadImagesToggle_, SIGNAL(triggered()),
452           this, SLOT(setAutoLoadImages()));
453   connect(mainWindow_->browserToolbarToggle_, SIGNAL(triggered()),
454           this, SLOT(setWebToolbarVisible()));
455 
456   connect(locationBar_, SIGNAL(returnPressed()),this, SLOT(slotUrlEnter()));
457   connect(webView_, SIGNAL(rssChanged(bool)), locationBar_, SLOT(showRssIcon(bool)));
458   connect(webView_, SIGNAL(urlChanged(QUrl)),
459           this, SLOT(slotUrlChanged(QUrl)), Qt::QueuedConnection);
460 }
461 
462 /** @brief Read settings from ini-file
463  *----------------------------------------------------------------------------*/
setSettings(bool init,bool newTab)464 void NewsTabWidget::setSettings(bool init, bool newTab)
465 {
466   Settings settings;
467 
468   if (type_ == TabTypeDownloads) return;
469 
470   QString style = settings.value("Settings/styleApplication", "defaultStyle_").toString();
471   if (style == "darkStyle_")
472     newsIconMovie_->setFileName(":/images/loading_dark");
473   else
474     newsIconMovie_->setFileName(":/images/loading");
475 
476   if (newTab) {
477     if (type_ < TabTypeWeb) {
478       newsTabWidgetSplitter_->restoreState(settings.value("NewsTabSplitterState").toByteArray());
479       QString iconStr = settings.value("Settings/newsToolBarIconSize", "toolBarIconSmall_").toString();
480       mainWindow_->setToolBarIconSize(newsToolBar_, iconStr);
481 
482       newsView_->setFont(
483             QFont(mainWindow_->newsListFontFamily_, mainWindow_->newsListFontSize_));
484       newsModel_->formatDate_ = mainWindow_->formatDate_;
485       newsModel_->formatTime_ = mainWindow_->formatTime_;
486       newsModel_->simplifiedDateTime_ = mainWindow_->simplifiedDateTime_;
487 
488       newsModel_->textColor_ = mainWindow_->newsListTextColor_;
489       newsView_->setStyleSheet(QString("#newsView_ {background: %1;}").arg(mainWindow_->newsListBackgroundColor_));
490       newsModel_->newNewsTextColor_ = mainWindow_->newNewsTextColor_;
491       newsModel_->unreadNewsTextColor_ = mainWindow_->unreadNewsTextColor_;
492       newsModel_->focusedNewsTextColor_ = mainWindow_->focusedNewsTextColor_;
493       newsModel_->focusedNewsBGColor_ = mainWindow_->focusedNewsBGColor_;
494 
495       QString styleSheetNews = settings.value("Settings/styleSheetNews",
496                                               mainApp->styleSheetNewsDefaultFile()).toString();
497       QFile file(styleSheetNews);
498       if (!file.open(QFile::ReadOnly)) {
499         file.setFileName(":/style/newsStyle");
500         file.open(QFile::ReadOnly);
501       }
502       cssString_ = QString::fromUtf8(file.readAll()).
503           arg(mainWindow_->newsTextFontFamily_).
504           arg(mainWindow_->newsTextFontSize_).
505           arg(mainWindow_->newsTitleFontFamily_).
506           arg(mainWindow_->newsTitleFontSize_).
507           arg(0).
508           arg(qApp->palette().color(QPalette::Dark).name()). // color separator
509           arg(mainWindow_->newsBackgroundColor_). // news background
510           arg(mainWindow_->newsTitleBackgroundColor_). // title background
511           arg(mainWindow_->linkColor_). // link color
512           arg(mainWindow_->titleColor_). // title color
513           arg(mainWindow_->dateColor_). // date color
514           arg(mainWindow_->authorColor_). // author color
515           arg(mainWindow_->newsTextColor_); // text color
516       file.close();
517 
518       file.setFileName(":/html/audioplayer");
519       file.open(QFile::ReadOnly);
520       audioPlayerHtml_ = QString::fromUtf8(file.readAll());
521       file.close();
522 
523       file.setFileName(":/html/videoplayer");
524       file.open(QFile::ReadOnly);
525       videoPlayerHtml_ = QString::fromUtf8(file.readAll());
526       file.close();
527     }
528 
529     if (mainWindow_->externalBrowserOn_ <= 0) {
530       webView_->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
531     } else {
532       webView_->page()->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks);
533     }
534 
535     webView_->page()->action(QWebPage::Back)->setShortcut(mainWindow_->backWebPageAct_->shortcut());
536     webView_->page()->action(QWebPage::Forward)->setShortcut(mainWindow_->forwardWebPageAct_->shortcut());
537     webView_->page()->action(QWebPage::Reload)->setShortcut(mainWindow_->reloadWebPageAct_->shortcut());
538 
539     QWebSettings::setObjectCacheCapacities(0, 0, 0);
540   }
541 
542   QModelIndex feedIndex = feedsModel_->indexById(feedId_);
543 
544   if (init) {
545     QWebSettings::clearMemoryCaches();
546 
547     if (type_ == TabTypeFeed) {
548       int displayEmbeddedImages = feedsModel_->dataField(feedIndex, "displayEmbeddedImages").toInt();
549       if (displayEmbeddedImages == 2) {
550         autoLoadImages_ = true;
551       } else if (displayEmbeddedImages == 1) {
552         autoLoadImages_ = mainWindow_->autoLoadImages_;
553       } else {
554         autoLoadImages_ = false;
555       }
556     } else {
557       autoLoadImages_ = mainWindow_->autoLoadImages_;
558     }
559     webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages_);
560 
561     webView_->setZoomFactor(qreal(mainWindow_->defaultZoomPages_)/100.0);
562   }
563   setAutoLoadImages(false);
564 
565   if (type_ == TabTypeFeed) {
566     int javaScriptEnable = feedsModel_->dataField(feedIndex, "javaScriptEnable").toInt();
567     if (javaScriptEnable == 2) {
568       webView_->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
569     } else if (javaScriptEnable == 1) {
570       webView_->settings()->setAttribute(QWebSettings::JavascriptEnabled, mainWindow_->javaScriptEnable_);
571     } else if (javaScriptEnable == 0) {
572       webView_->settings()->setAttribute(QWebSettings::JavascriptEnabled, false);
573     }
574 
575     int layoutDirection = feedsModel_->dataField(feedIndex, "layoutDirection").toInt();
576     if (!layoutDirection) {
577       newsView_->setLayoutDirection(Qt::LeftToRight);
578     } else {
579       newsView_->setLayoutDirection(Qt::RightToLeft);
580     }
581   } else {
582     webView_->settings()->setAttribute(QWebSettings::JavascriptEnabled, mainWindow_->javaScriptEnable_);
583   }
584 
585   if (type_ < TabTypeWeb) {
586     newsView_->setAlternatingRowColors(mainWindow_->alternatingRowColorsNews_);
587 
588     QPalette palette = newsView_->palette();
589     palette.setColor(QPalette::AlternateBase, mainWindow_->alternatingRowColors_);
590     newsView_->setPalette(palette);
591 
592     if (!newTab)
593       newsModel_->setFilter("feedId=-1");
594     newsHeader_->setColumns(feedIndex);
595     mainWindow_->slotUpdateStatus(feedId_, false);
596     mainWindow_->newsFilter_->setEnabled(type_ == TabTypeFeed);
597     separatorRAct_->setVisible(type_ == TabTypeDel);
598     mainWindow_->restoreNewsAct_->setVisible(type_ == TabTypeDel);
599 
600     switch (mainWindow_->newsLayout_) {
601     case 1:
602       newsWidget_->setVisible(false);
603       break;
604     default:
605       newsWidget_->setVisible(true);
606     }
607   }
608 }
609 
610 /** @brief Reload translation
611  *----------------------------------------------------------------------------*/
retranslateStrings()612 void NewsTabWidget::retranslateStrings() {
613   if (type_ != TabTypeDownloads) {
614     webViewProgress_->setFormat(tr("Loading... (%p%)"));
615 
616     webHomePageAct_->setText(tr("Home"));
617     webExternalBrowserAct_->setText(tr("Open Page in External Browser"));
618     urlExternalBrowserAct_->setText(tr("Open Link in External Browser"));
619 
620     if (type_ != TabTypeWeb) {
621       findText_->retranslateStrings();
622       newsHeader_->retranslateStrings();
623     }
624 
625     if (mainWindow_->currentNewsTab == this) {
626       if (autoLoadImages_) {
627         mainWindow_->autoLoadImagesToggle_->setText(tr("Load Images"));
628         mainWindow_->autoLoadImagesToggle_->setToolTip(tr("Auto Load Images to News View"));
629       } else {
630         mainWindow_->autoLoadImagesToggle_->setText(tr("No Load Images"));
631         mainWindow_->autoLoadImagesToggle_->setToolTip(tr("No Load Images to News View"));
632       }
633     }
634   }
635 
636   closeButton_->setToolTip(tr("Close Tab"));
637 }
638 
setAutoLoadImages(bool apply)639 void NewsTabWidget::setAutoLoadImages(bool apply)
640 {
641   if (type_ == NewsTabWidget::TabTypeDownloads) return;
642   if (mainWindow_->currentNewsTab != this) return;
643 
644   if (apply)
645     autoLoadImages_ = !autoLoadImages_;
646 
647   if (autoLoadImages_) {
648     mainWindow_->autoLoadImagesToggle_->setText(tr("Load Images"));
649     mainWindow_->autoLoadImagesToggle_->setToolTip(tr("Auto Load Images in News View"));
650     mainWindow_->autoLoadImagesToggle_->setIcon(QIcon(":/images/imagesOn"));
651   } else {
652     mainWindow_->autoLoadImagesToggle_->setText(tr("Don't Load Images"));
653     mainWindow_->autoLoadImagesToggle_->setToolTip(tr("Don't Load Images in News View"));
654     mainWindow_->autoLoadImagesToggle_->setIcon(QIcon(":/images/imagesOff"));
655   }
656 
657   if (apply) {
658     webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages_);
659     if (autoLoadImages_) {
660       if ((webView_->title() == "news_descriptions") &&
661           (type_ == NewsTabWidget::TabTypeFeed)) {
662         switch (mainWindow_->newsLayout_) {
663         case 1:
664           loadNewspaper();
665           break;
666         default:
667           updateWebView(newsView_->currentIndex());
668         }
669       } else {
670         webView_->reload();
671       }
672     }
673   }
674 }
675 
676 /** @brief Process mouse click in news list
677  *----------------------------------------------------------------------------*/
slotNewsViewClicked(QModelIndex index)678 void NewsTabWidget::slotNewsViewClicked(QModelIndex index)
679 {
680   slotNewsViewSelected(index);
681 }
682 
683 // ----------------------------------------------------------------------------
slotNewsViewSelected(QModelIndex index,bool clicked)684 void NewsTabWidget::slotNewsViewSelected(QModelIndex index, bool clicked)
685 {
686   if (mainWindow_->newsLayout_ == 1) return;
687 
688   int newsId = newsModel_->dataField(index.row(), "id").toInt();
689   if (mainWindow_->markNewsReadOn_ && mainWindow_->markPrevNewsRead_ &&
690       (newsId != currentNewsIdOld)) {
691     QModelIndex startIndex = newsModel_->index(0, newsModel_->fieldIndex("id"));
692     QModelIndexList indexList = newsModel_->match(startIndex, Qt::EditRole, currentNewsIdOld);
693     if (!indexList.isEmpty()) {
694       slotSetItemRead(indexList.first(), 1);
695     }
696   }
697 
698   if (!index.isValid()) {
699     hideWebContent();
700     currentNewsIdOld = newsId;
701     return;
702   }
703 
704   if (!((newsId == currentNewsIdOld) &&
705         newsModel_->dataField(index.row(), "read").toInt() >= 1) ||
706       clicked) {
707     markNewsReadTimer_->stop();
708     if (mainWindow_->markNewsReadOn_ && mainWindow_->markCurNewsRead_) {
709       if (mainWindow_->markNewsReadTime_ == 0) {
710         slotSetItemRead(index, 1);
711       } else {
712         markNewsReadTimer_->start(mainWindow_->markNewsReadTime_*1000);
713       }
714     }
715 
716     if (type_ == TabTypeFeed) {
717       // Write current news to feed
718       QString qStr = QString("UPDATE feeds SET currentNews='%1' WHERE id=='%2'").
719           arg(newsId).arg(feedId_);
720       mainApp->sqlQueryExec(qStr);
721 
722       QModelIndex feedIndex = feedsModel_->indexById(feedId_);
723       feedsModel_->setData(feedsModel_->indexSibling(feedIndex, "currentNews"), newsId);
724     } else if (type_ == TabTypeLabel) {
725       QString qStr = QString("UPDATE labels SET currentNews='%1' WHERE id=='%2'").
726           arg(newsId).
727           arg(mainWindow_->categoriesTree_->currentItem()->text(2).toInt());
728       mainApp->sqlQueryExec(qStr);
729 
730       mainWindow_->categoriesTree_->currentItem()->setText(3, QString::number(newsId));
731     }
732 
733     updateWebView(index);
734     mainWindow_->statusBar()->showMessage(linkNewsString_, 3000);
735   }
736   currentNewsIdOld = newsId;
737 }
738 
739 // ----------------------------------------------------------------------------
slotNewsViewDoubleClicked(QModelIndex index)740 void NewsTabWidget::slotNewsViewDoubleClicked(QModelIndex index)
741 {
742   if (!index.isValid()) return;
743 
744   QUrl url = QUrl::fromEncoded(getLinkNews(index.row()).toUtf8());
745   slotLinkClicked(url);
746 }
747 
748 // ----------------------------------------------------------------------------
slotNewsMiddleClicked(QModelIndex index)749 void NewsTabWidget::slotNewsMiddleClicked(QModelIndex index)
750 {
751   if (!index.isValid()) return;
752 
753   if (mainWindow_->markNewsReadOn_ && mainWindow_->markCurNewsRead_)
754     slotSetItemRead(index, 1);
755 
756   if (QApplication::keyboardModifiers() == Qt::NoModifier) {
757     webView_->buttonClick_ = MIDDLE_BUTTON;
758   } else if (QApplication::keyboardModifiers() == Qt::AltModifier) {
759     webView_->buttonClick_ = LEFT_BUTTON_ALT;
760   } else {
761     webView_->buttonClick_ = MIDDLE_BUTTON_MOD;
762   }
763 
764   QUrl url = QUrl::fromEncoded(getLinkNews(index.row()).toUtf8());
765   slotLinkClicked(url);
766 }
767 
768 /** @brief Process pressing UP-key
769  *----------------------------------------------------------------------------*/
slotNewsUpPressed(QModelIndex index)770 void NewsTabWidget::slotNewsUpPressed(QModelIndex index)
771 {
772   if (type_ >= TabTypeWeb) return;
773 
774   int row;
775   if (!index.isValid()) {
776     if (!newsView_->currentIndex().isValid())
777       row = 0;
778     else
779       row = newsView_->currentIndex().row() - 1;
780     if (row < 0)
781       return;
782     index = newsModel_->index(row, newsModel_->fieldIndex("title"));
783     newsView_->setCurrentIndex(index);
784   } else {
785     row = index.row();
786   }
787 
788   int value = newsView_->verticalScrollBar()->value();
789   int pageStep = newsView_->verticalScrollBar()->pageStep();
790   if (row < (value + pageStep/2))
791     newsView_->verticalScrollBar()->setValue(row - pageStep/2);
792 
793   slotNewsViewSelected(index);
794 }
795 
796 /** @brief Process pressing DOWN-key
797  *----------------------------------------------------------------------------*/
slotNewsDownPressed(QModelIndex index)798 void NewsTabWidget::slotNewsDownPressed(QModelIndex index)
799 {
800   if (type_ >= TabTypeWeb) return;
801 
802   int row;
803   if (!index.isValid()) {
804     if (!newsView_->currentIndex().isValid())
805       row = 0;
806     else
807       row = newsView_->currentIndex().row() + 1;
808     if (row >= newsModel_->rowCount())
809       return;
810     index = newsModel_->index(row, newsModel_->fieldIndex("title"));
811     newsView_->setCurrentIndex(index);
812   } else {
813     row = index.row();
814   }
815 
816   int value = newsView_->verticalScrollBar()->value();
817   int pageStep = newsView_->verticalScrollBar()->pageStep();
818   if (row > (value + pageStep/2))
819     newsView_->verticalScrollBar()->setValue(row - pageStep/2);
820   slotNewsViewSelected(index);
821 }
822 
823 /** @brief Process pressing HOME-key
824  *----------------------------------------------------------------------------*/
slotNewsHomePressed(QModelIndex index)825 void NewsTabWidget::slotNewsHomePressed(QModelIndex index)
826 {
827   slotNewsViewSelected(index);
828 }
829 
830 /** @brief Process pressing END-key
831  *----------------------------------------------------------------------------*/
slotNewsEndPressed(QModelIndex index)832 void NewsTabWidget::slotNewsEndPressed(QModelIndex index)
833 {
834   slotNewsViewSelected(index);
835 }
836 
837 /** @brief Process pressing PageUp-key
838  *----------------------------------------------------------------------------*/
slotNewsPageUpPressed(QModelIndex index)839 void NewsTabWidget::slotNewsPageUpPressed(QModelIndex index)
840 {
841   int row;
842   if (!index.isValid()) {
843     if (!newsView_->currentIndex().isValid())
844       row = 0;
845     else
846       row = newsView_->currentIndex().row() - newsView_->verticalScrollBar()->pageStep();
847     if (row < 0)
848       row = 0;
849     index = newsModel_->index(row, newsModel_->fieldIndex("title"));
850     newsView_->setCurrentIndex(index);
851   }
852 
853   slotNewsViewSelected(index);
854 }
855 
856 /** @brief Process pressing PageDown-key
857  *----------------------------------------------------------------------------*/
slotNewsPageDownPressed(QModelIndex index)858 void NewsTabWidget::slotNewsPageDownPressed(QModelIndex index)
859 {
860   int row;
861   if (!index.isValid()) {
862     if (!newsView_->currentIndex().isValid())
863       row = 0;
864     else
865       row = newsView_->currentIndex().row() + newsView_->verticalScrollBar()->pageStep();
866     if (row >= newsModel_->rowCount())
867       row = newsModel_->rowCount()-1;
868     index = newsModel_->index(row, newsModel_->fieldIndex("title"));
869     newsView_->setCurrentIndex(index);
870   }
871 
872   slotNewsViewSelected(index);
873 }
874 
875 /** @brief Mark news Read
876  *----------------------------------------------------------------------------*/
slotSetItemRead(QModelIndex index,int read)877 void NewsTabWidget::slotSetItemRead(QModelIndex index, int read)
878 {
879   markNewsReadTimer_->stop();
880   if (!index.isValid() || (newsModel_->rowCount() == 0)) return;
881 
882   bool changed = false;
883   int newsId = newsModel_->dataField(index.row(), "id").toInt();
884 
885   if (read == 1) {
886     if (newsModel_->dataField(index.row(), "new").toInt() == 1) {
887       newsModel_->setData(
888             newsModel_->index(index.row(), newsModel_->fieldIndex("new")),
889             0);
890       mainApp->sqlQueryExec(QString("UPDATE news SET new=0 WHERE id=='%1'").arg(newsId));
891     }
892     if (newsModel_->dataField(index.row(), "read").toInt() == 0) {
893       newsModel_->setData(
894             newsModel_->index(index.row(), newsModel_->fieldIndex("read")),
895             1);
896       mainApp->sqlQueryExec(QString("UPDATE news SET read=1 WHERE id=='%1'").arg(newsId));
897       changed = true;
898     }
899   } else {
900     if (newsModel_->dataField(index.row(), "read").toInt() != 0) {
901       newsModel_->setData(
902             newsModel_->index(index.row(), newsModel_->fieldIndex("read")),
903             0);
904       mainApp->sqlQueryExec(QString("UPDATE news SET read=0 WHERE id=='%1'").arg(newsId));
905       changed = true;
906     }
907   }
908 
909   if (changed) {
910     newsView_->viewport()->update();
911     int feedId = newsModel_->dataField(index.row(), "feedId").toInt();
912     mainWindow_->slotUpdateStatus(feedId);
913     mainWindow_->recountCategoryCounts();
914   }
915 }
916 
917 /** @brief Mark news Star
918  *----------------------------------------------------------------------------*/
slotSetItemStar(QModelIndex index,int starred)919 void NewsTabWidget::slotSetItemStar(QModelIndex index, int starred)
920 {
921   if (!index.isValid()) return;
922 
923   newsModel_->setData(index, starred);
924 
925   int newsId = newsModel_->dataField(index.row(), "id").toInt();
926   mainApp->sqlQueryExec(QString("UPDATE news SET starred='%1' WHERE id=='%2'").
927                         arg(starred).arg(newsId));
928   mainWindow_->recountCategoryCounts();
929 }
930 
slotMarkReadTimeout()931 void NewsTabWidget::slotMarkReadTimeout()
932 {
933   slotSetItemRead(newsView_->currentIndex(), 1);
934 }
935 
936 /** @brief Mark selected news Read
937  *----------------------------------------------------------------------------*/
markNewsRead()938 void NewsTabWidget::markNewsRead()
939 {
940   if (type_ >= TabTypeWeb) return;
941   markNewsReadTimer_->stop();
942 
943   QModelIndex curIndex;
944   QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(0);
945 
946   int cnt = indexes.count();
947   if (cnt == 0) return;
948 
949   if (cnt == 1) {
950     curIndex = indexes.at(0);
951     if (newsModel_->dataField(curIndex.row(), "read").toInt() == 0) {
952       slotSetItemRead(curIndex, 1);
953     } else {
954       slotSetItemRead(curIndex, 0);
955     }
956   } else {
957     QStringList feedIdList;
958 
959     bool markRead = false;
960     for (int i = cnt-1; i >= 0; --i) {
961       curIndex = indexes.at(i);
962       if (newsModel_->dataField(curIndex.row(), "read").toInt() == 0) {
963         markRead = true;
964         break;
965       }
966     }
967 
968     db_.transaction();
969     QSqlQuery q;
970     for (int i = cnt-1; i >= 0; --i) {
971       curIndex = indexes.at(i);
972       newsModel_->setData(
973             newsModel_->index(curIndex.row(), newsModel_->fieldIndex("new")),
974             0);
975       newsModel_->setData(
976             newsModel_->index(curIndex.row(), newsModel_->fieldIndex("read")),
977             markRead);
978 
979       int newsId = newsModel_->dataField(curIndex.row(), "id").toInt();
980       q.exec(QString("UPDATE news SET new=0, read='%1' WHERE id=='%2'").
981              arg(markRead).arg(newsId));
982       QString feedId = newsModel_->dataField(curIndex.row(), "feedId").toString();
983       if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
984     }
985     db_.commit();
986 
987     foreach (QString feedId, feedIdList) {
988       mainWindow_->slotUpdateStatus(feedId.toInt());
989     }
990     mainWindow_->recountCategoryCounts();
991     newsView_->viewport()->update();
992   }
993 }
994 
995 /** @brief Mark all news of the feed Read
996  *----------------------------------------------------------------------------*/
markAllNewsRead()997 void NewsTabWidget::markAllNewsRead()
998 {
999   if (type_ >= TabTypeWeb) return;
1000   markNewsReadTimer_->stop();
1001 
1002   int cnt = newsModel_->rowCount();
1003   if (cnt == 0) return;
1004 
1005   QStringList feedIdList;
1006 
1007   db_.transaction();
1008   QSqlQuery q;
1009   for (int i = cnt-1; i >= 0; --i) {
1010     int newsId = newsModel_->dataField(i, "id").toInt();
1011     q.exec(QString("UPDATE news SET read=1 WHERE id=='%1' AND read=0").arg(newsId));
1012     q.exec(QString("UPDATE news SET new=0 WHERE id=='%1' AND new=1").arg(newsId));
1013 
1014     QString feedId = newsModel_->dataField(i, "feedId").toString();
1015     if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
1016   }
1017   db_.commit();
1018 
1019   int currentRow = newsView_->currentIndex().row();
1020 
1021   newsModel_->select();
1022 
1023   while (newsModel_->canFetchMore())
1024     newsModel_->fetchMore();
1025 
1026   loadNewspaper(RefreshWithPos);
1027 
1028   newsView_->setCurrentIndex(newsModel_->index(currentRow, newsModel_->fieldIndex("title")));
1029 
1030   foreach (QString feedId, feedIdList) {
1031     mainWindow_->slotUpdateStatus(feedId.toInt());
1032   }
1033   mainWindow_->recountCategoryCounts();
1034 }
1035 
1036 /** @brief Mark selected news Starred
1037  *----------------------------------------------------------------------------*/
markNewsStar()1038 void NewsTabWidget::markNewsStar()
1039 {
1040   if (type_ >= TabTypeWeb) return;
1041 
1042   QModelIndex curIndex;
1043   QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(
1044         newsModel_->fieldIndex("starred"));
1045 
1046   int cnt = indexes.count();
1047   if (cnt == 0) return;
1048 
1049   if (cnt == 1) {
1050     curIndex = indexes.at(0);
1051     if (curIndex.data(Qt::EditRole).toInt() == 0) {
1052       slotSetItemStar(curIndex, 1);
1053     } else {
1054       slotSetItemStar(curIndex, 0);
1055     }
1056   } else {
1057     bool markStar = false;
1058     for (int i = cnt-1; i >= 0; --i) {
1059       curIndex = indexes.at(i);
1060       if (curIndex.data(Qt::EditRole).toInt() == 0) {
1061         markStar = true;
1062         break;
1063       }
1064     }
1065 
1066     db_.transaction();
1067     for (int i = cnt-1; i >= 0; --i) {
1068       curIndex = indexes.at(i);
1069       newsModel_->setData(curIndex, markStar);
1070 
1071       int newsId = newsModel_->dataField(curIndex.row(), "id").toInt();
1072       QSqlQuery q;
1073       q.exec(QString("UPDATE news SET starred='%1' WHERE id=='%2'").
1074              arg(markStar).arg(newsId));
1075     }
1076     db_.commit();
1077 
1078     mainWindow_->recountCategoryCounts();
1079   }
1080 }
1081 
1082 /** @brief Delete selected news
1083  *----------------------------------------------------------------------------*/
deleteNews()1084 void NewsTabWidget::deleteNews()
1085 {
1086   if (type_ >= TabTypeWeb) return;
1087 
1088   QModelIndex curIndex;
1089   QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(newsModel_->fieldIndex("deleted"));
1090 
1091   int cnt = indexes.count();
1092   if (cnt == 0) return;
1093 
1094   QStringList feedIdList;
1095 
1096   if (type_ != TabTypeDel) {
1097     if (cnt == 1) {
1098       curIndex = indexes.at(0);
1099       if (newsModel_->dataField(curIndex.row(), "starred").toInt() &&
1100           mainWindow_->notDeleteStarred_)
1101         return;
1102       QString labelStr = newsModel_->dataField(curIndex.row(), "label").toString();
1103       if (!(labelStr.isEmpty() || (labelStr == ",")) && mainWindow_->notDeleteLabeled_)
1104         return;
1105 
1106       slotSetItemRead(curIndex, 1);
1107 
1108       newsModel_->setData(curIndex, 1);
1109       newsModel_->setData(newsModel_->index(curIndex.row(), newsModel_->fieldIndex("deleteDate")),
1110                           QDateTime::currentDateTime().toString(Qt::ISODate));
1111 
1112       QString feedId = newsModel_->dataField(curIndex.row(), "feedId").toString();
1113       if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
1114 
1115       newsModel_->submitAll();
1116     } else {
1117       db_.transaction();
1118       QSqlQuery q;
1119       for (int i = cnt-1; i >= 0; --i) {
1120         curIndex = indexes.at(i);
1121         if (newsModel_->dataField(curIndex.row(), "starred").toInt() &&
1122             mainWindow_->notDeleteStarred_)
1123           continue;
1124         QString labelStr = newsModel_->dataField(curIndex.row(), "label").toString();
1125         if (!(labelStr.isEmpty() || (labelStr == ",")) && mainWindow_->notDeleteLabeled_)
1126           continue;
1127 
1128         int newsId = newsModel_->dataField(curIndex.row(), "id").toInt();
1129         q.exec(QString("UPDATE news SET new=0, read=2, deleted=1, deleteDate='%1' WHERE id=='%2'").
1130                arg(QDateTime::currentDateTime().toString(Qt::ISODate)).
1131                arg(newsId));
1132 
1133         QString feedId = newsModel_->dataField(curIndex.row(), "feedId").toString();
1134         if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
1135       }
1136       db_.commit();
1137 
1138       newsModel_->select();
1139     }
1140   }
1141   else {
1142     db_.transaction();
1143     QSqlQuery q;
1144     for (int i = cnt-1; i >= 0; --i) {
1145       curIndex = indexes.at(i);
1146 
1147       int newsId = newsModel_->dataField(curIndex.row(), "id").toInt();
1148       q.exec(QString("UPDATE news SET description='', content='', received='', "
1149                      "author_name='', author_uri='', author_email='', "
1150                      "category='', new='', read='', starred='', label='', "
1151                      "deleteDate='', feedParentId='', deleted=2 WHERE id=='%1'").
1152              arg(newsId));
1153 
1154       QString feedId = newsModel_->dataField(curIndex.row(), "feedId").toString();
1155       if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
1156     }
1157     db_.commit();
1158 
1159     newsModel_->select();
1160   }
1161 
1162   while (newsModel_->canFetchMore())
1163     newsModel_->fetchMore();
1164 
1165   if (curIndex.row() == newsModel_->rowCount())
1166     curIndex = newsModel_->index(curIndex.row()-1, newsModel_->fieldIndex("title"));
1167   else if (curIndex.row() > newsModel_->rowCount())
1168     curIndex = newsModel_->index(newsModel_->rowCount()-1, newsModel_->fieldIndex("title"));
1169   else
1170     curIndex = newsModel_->index(curIndex.row(), newsModel_->fieldIndex("title"));
1171   newsView_->setCurrentIndex(curIndex);
1172   slotNewsViewSelected(curIndex);
1173 
1174   foreach (QString feedId, feedIdList) {
1175     mainWindow_->slotUpdateStatus(feedId.toInt());
1176   }
1177   mainWindow_->recountCategoryCounts();
1178 }
1179 
1180 /** @brief Delete all news of the feed
1181  *----------------------------------------------------------------------------*/
deleteAllNewsList()1182 void NewsTabWidget::deleteAllNewsList()
1183 {
1184   if (type_ >= TabTypeWeb) return;
1185 
1186   int cnt = newsModel_->rowCount();
1187   if (cnt == 0) return;
1188 
1189   QStringList feedIdList;
1190 
1191   db_.transaction();
1192   QSqlQuery q;
1193   for (int i = cnt-1; i >= 0; --i) {
1194     int newsId = newsModel_->dataField(i, "id").toInt();
1195 
1196     if (type_ != TabTypeDel) {
1197       if (newsModel_->dataField(i, "starred").toInt() &&
1198           mainWindow_->notDeleteStarred_)
1199         continue;
1200       QString labelStr = newsModel_->dataField(i, "label").toString();
1201       if (!(labelStr.isEmpty() || (labelStr == ",")) && mainWindow_->notDeleteLabeled_)
1202         continue;
1203 
1204       q.exec(QString("UPDATE news SET new=0, read=2, deleted=1, deleteDate='%1' WHERE id=='%2'").
1205              arg(QDateTime::currentDateTime().toString(Qt::ISODate)).
1206              arg(newsId));
1207     }
1208     else {
1209       q.exec(QString("UPDATE news SET description='', content='', received='', "
1210                      "author_name='', author_uri='', author_email='', "
1211                      "category='', new='', read='', starred='', label='', "
1212                      "deleteDate='', feedParentId='', deleted=2 WHERE id=='%1'").
1213              arg(newsId));
1214     }
1215 
1216     QString feedId = newsModel_->dataField(i, "feedId").toString();
1217     if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
1218   }
1219   db_.commit();
1220 
1221   newsModel_->select();
1222 
1223   slotNewsViewSelected(QModelIndex());
1224 
1225   foreach (QString feedId, feedIdList) {
1226     mainWindow_->slotUpdateStatus(feedId.toInt());
1227   }
1228   mainWindow_->recountCategoryCounts();
1229 }
1230 
1231 /** @brief Restore deleted news
1232  *----------------------------------------------------------------------------*/
restoreNews()1233 void NewsTabWidget::restoreNews()
1234 {
1235   if (type_ >= TabTypeWeb) return;
1236 
1237   QModelIndex curIndex;
1238   QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(newsModel_->fieldIndex("deleted"));
1239 
1240   int cnt = indexes.count();
1241   if (cnt == 0) return;
1242 
1243   QStringList feedIdList;
1244 
1245   if (cnt == 1) {
1246     curIndex = indexes.at(0);
1247     newsModel_->setData(curIndex, 0);
1248     newsModel_->setData(newsModel_->index(curIndex.row(), newsModel_->fieldIndex("deleteDate")), "");
1249     newsModel_->submitAll();
1250 
1251     QString feedId = newsModel_->dataField(curIndex.row(), "feedId").toString();
1252     if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
1253   } else {
1254     db_.transaction();
1255     QSqlQuery q;
1256     for (int i = cnt-1; i >= 0; --i) {
1257       curIndex = indexes.at(i);
1258       int newsId = newsModel_->dataField(curIndex.row(), "id").toInt();
1259       q.exec(QString("UPDATE news SET deleted=0, deleteDate='' WHERE id=='%1'").
1260              arg(newsId));
1261 
1262       QString feedId = newsModel_->dataField(curIndex.row(), "feedId").toString();
1263       if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
1264     }
1265     db_.commit();
1266 
1267     newsModel_->select();
1268   }
1269 
1270   while (newsModel_->canFetchMore())
1271     newsModel_->fetchMore();
1272 
1273   loadNewspaper(RefreshWithPos);
1274 
1275   if (curIndex.row() == newsModel_->rowCount())
1276     curIndex = newsModel_->index(curIndex.row()-1, newsModel_->fieldIndex("title"));
1277   else if (curIndex.row() > newsModel_->rowCount())
1278     curIndex = newsModel_->index(newsModel_->rowCount()-1, newsModel_->fieldIndex("title"));
1279   else
1280     curIndex = newsModel_->index(curIndex.row(), newsModel_->fieldIndex("title"));
1281   newsView_->setCurrentIndex(curIndex);
1282   slotNewsViewSelected(curIndex);
1283   mainWindow_->slotUpdateStatus(feedId_);
1284   mainWindow_->recountCategoryCounts();
1285 
1286   foreach (QString feedId, feedIdList) {
1287     mainWindow_->slotUpdateStatus(feedId.toInt());
1288   }
1289   mainWindow_->recountCategoryCounts();
1290 }
1291 
1292 /** @brief Copy news link
1293  *----------------------------------------------------------------------------*/
slotCopyLinkNews()1294 void NewsTabWidget::slotCopyLinkNews()
1295 {
1296   if (type_ >= TabTypeWeb) return;
1297 
1298   QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(0);
1299 
1300   int cnt = indexes.count();
1301   if (cnt == 0) return;
1302 
1303   QString copyStr;
1304   for (int i = cnt-1; i >= 0; --i) {
1305     if (!copyStr.isEmpty()) copyStr.append("\n");
1306     copyStr.append(getLinkNews(indexes.at(i).row()));
1307   }
1308 
1309   QClipboard *clipboard = QApplication::clipboard();
1310   clipboard->setText(copyStr);
1311 }
1312 
1313 /** @brief Sort news by Star or Read column
1314  *----------------------------------------------------------------------------*/
slotSort(int column,int)1315 void NewsTabWidget::slotSort(int column, int/* order*/)
1316 {
1317   QString strId;
1318   if (feedsModel_->isFolder(feedsModel_->indexById(feedId_))) {
1319     strId = QString("(%1)").arg(mainWindow_->getIdFeedsString(feedId_));
1320   } else {
1321     strId = QString("feedId='%1'").arg(feedId_);
1322   }
1323 
1324   QString qStr;
1325   if (column == newsModel_->fieldIndex("read")) {
1326     qStr = QString("UPDATE news SET rights=read WHERE %1").arg(strId);
1327   }
1328   else if (column == newsModel_->fieldIndex("starred")) {
1329     qStr = QString("UPDATE news SET rights=starred WHERE %1").arg(strId);
1330   }
1331   else if (column == newsModel_->fieldIndex("rights")) {
1332     qStr = QString("UPDATE news SET rights = (SELECT text from feeds where id = news.feedId) WHERE %1").arg(strId);
1333   }
1334 
1335   QSqlQuery q;
1336   q.exec(qStr);
1337 }
1338 
1339 /** @brief Load/Update browser contents
1340  *----------------------------------------------------------------------------*/
updateWebView(QModelIndex index)1341 void NewsTabWidget::updateWebView(QModelIndex index)
1342 {
1343   if (!index.isValid()) {
1344     hideWebContent();
1345     return;
1346   }
1347 
1348   QString newsId = newsModel_->dataField(index.row(), "id").toString();
1349   linkNewsString_ = getLinkNews(index.row());
1350   QString linkString = linkNewsString_;
1351   QUrl newsUrl = QUrl::fromEncoded(linkString.toUtf8());
1352 
1353   bool showDescriptionNews_ = mainWindow_->showDescriptionNews_;
1354   QModelIndex currentIndex = feedsProxyModel_->mapToSource(feedsView_->currentIndex());
1355   QVariant displayNews = feedsModel_->dataField(currentIndex, "displayNews");
1356   QString feedId = newsModel_->dataField(index.row(), "feedId").toString();
1357   QModelIndex feedIndex = feedsModel_->indexById(feedId.toInt());
1358 
1359   if (!displayNews.toString().isEmpty())
1360     showDescriptionNews_ = !displayNews.toInt();
1361 
1362   if (!showDescriptionNews_) {
1363     if (mainWindow_->externalBrowserOn_ <= 0) {
1364       locationBar_->setText(newsUrl.toString());
1365       setWebToolbarVisible(true, false);
1366 
1367       webView_->history()->setMaximumItemCount(0);
1368       webView_->load(newsUrl);
1369       webView_->history()->setMaximumItemCount(100);
1370     } else {
1371       openUrl(newsUrl);
1372     }
1373   } else {
1374     setWebToolbarVisible(false, false);
1375 
1376     QString htmlStr;
1377     QString content = newsModel_->dataField(index.row(), "content").toString();
1378     if (!content.contains(QzRegExp("<html(.*)</html>", Qt::CaseInsensitive))) {
1379       QString description = newsModel_->dataField(index.row(), "description").toString();
1380       if (content.isEmpty() || (description.length() > content.length())) {
1381         content = description;
1382       }
1383 
1384       QString titleString = newsModel_->dataField(index.row(), "title").toString();
1385       if (!linkString.isEmpty()) {
1386         titleString = QString("<a href='%1' class='unread'>%2</a>").
1387             arg(linkString, titleString);
1388       }
1389 
1390       QDateTime dtLocal;
1391       QString dateString = newsModel_->dataField(index.row(), "published").toString();
1392       if (!dateString.isNull()) {
1393         QDateTime dtLocalTime = QDateTime::currentDateTime();
1394         QDateTime dtUTC = QDateTime(dtLocalTime.date(), dtLocalTime.time(), Qt::UTC);
1395         int nTimeShift = dtLocalTime.secsTo(dtUTC);
1396 
1397         QDateTime dt = QDateTime::fromString(dateString, Qt::ISODate);
1398         dtLocal = dt.addSecs(nTimeShift);
1399       } else {
1400         dtLocal = QDateTime::fromString(
1401               newsModel_->dataField(index.row(), "received").toString(),
1402               Qt::ISODate);
1403       }
1404       if (QDateTime::currentDateTime().date() <= dtLocal.date())
1405         dateString = dtLocal.toString(mainWindow_->formatTime_);
1406       else
1407         dateString = dtLocal.toString(mainWindow_->formatDate_ + " " + mainWindow_->formatTime_);
1408 
1409       // Create author panel from news author
1410       QString authorString;
1411       QString authorName = newsModel_->dataField(index.row(), "author_name").toString();
1412       QString authorEmail = newsModel_->dataField(index.row(), "author_email").toString();
1413       QString authorUri = newsModel_->dataField(index.row(), "author_uri").toString();
1414 
1415       QzRegExp reg("(^\\S+@\\S+\\.\\S+)", Qt::CaseInsensitive);
1416       int pos = reg.indexIn(authorName);
1417       if (pos > -1) {
1418         authorName.replace(reg.cap(1), QString(" <a href='mailto:%1'>%1</a>").arg(reg.cap(1)));
1419       }
1420 
1421       authorString = authorName;
1422 
1423       if (!authorEmail.isEmpty())
1424         authorString.append(QString(" <a href='mailto:%1'>e-mail</a>").arg(authorEmail));
1425       if (!authorUri.isEmpty())
1426         authorString.append(QString(" <a href='%1'>page</a>"). arg(authorUri));
1427 
1428       // If news author is absent, create author panel from feed author
1429       // @note(arhohryakov:2012.01.03) Author is got from current feed, because
1430       //   news is belong to it
1431       if (authorString.isEmpty()) {
1432         authorName  = feedsModel_->dataField(feedIndex, "author_name").toString();
1433         authorEmail = feedsModel_->dataField(feedIndex, "author_email").toString();
1434         authorUri   = feedsModel_->dataField(feedIndex, "author_uri").toString();
1435 
1436         authorString = authorName;
1437 
1438         if (!authorEmail.isEmpty())
1439           authorString.append(QString(" <a href='mailto:%1'>e-mail</a>").arg(authorEmail));
1440         if (!authorUri.isEmpty())
1441           authorString.append(QString(" <a href='%1'>page</a>").arg(authorUri));
1442       }
1443 
1444       QString commentsStr;
1445       QString commentsUrl = newsModel_->dataField(index.row(), "comments").toString();
1446 
1447       if (!commentsUrl.isEmpty())
1448       {
1449         commentsStr = QString("<a href=\"%1\"> %2</a>").arg(commentsUrl, tr("Comments"));
1450       }
1451 
1452       QString category = newsModel_->dataField(index.row(), "category").toString();
1453 
1454       if (!authorString.isEmpty())
1455       {
1456         authorString = QString(tr("Author: %1")).arg(authorString);
1457 
1458         if (!commentsStr.isEmpty())
1459         {
1460           authorString.append(QString(" | %1").arg(commentsStr));
1461         }
1462         if (!category.isEmpty())
1463         {
1464           authorString.append(QString(" | %1").arg(category));
1465         }
1466       }
1467       else
1468       {
1469         if (!commentsStr.isEmpty())
1470         {
1471           authorString.append(commentsStr);
1472         }
1473 
1474         if (!category.isEmpty())
1475         {
1476           if (!commentsStr.isEmpty())
1477           {
1478             authorString.append(QString(" | %1").arg(category));
1479           }
1480           else
1481           {
1482             authorString.append(category);
1483           }
1484         }
1485       }
1486 
1487       QString labelsString = getHtmlLabels(index.row());
1488 
1489       authorString.append(QString("<table class=\"labels\" id=\"labels%1\"><tr>%2</tr></table>").
1490                           arg(newsId).arg(labelsString));
1491 
1492       QString enclosureStr;
1493       QString enclosureUrl = newsModel_->dataField(index.row(), "enclosure_url").toString();
1494 
1495       if (!enclosureUrl.isEmpty())
1496       {
1497         QString type = newsModel_->dataField(index.row(), "enclosure_type").toString();
1498 
1499         if (type.contains("image"))
1500         {
1501           if (!content.contains(enclosureUrl) && autoLoadImages_)
1502           {
1503             enclosureStr = QString("<IMG SRC=\"%1\" class=\"enclosureImg\"><p>").arg(enclosureUrl);
1504           }
1505         }
1506         else
1507         {
1508           if (type.contains("audio"))
1509           {
1510             type = tr("audio");
1511             enclosureStr = audioPlayerHtml_.arg(enclosureUrl);
1512             enclosureStr.append("<p>");
1513           }
1514           else if (type.contains("video"))
1515           {
1516             type = tr("video");
1517             enclosureStr = videoPlayerHtml_.arg(enclosureUrl);
1518             enclosureStr.append("<p>");
1519           }
1520           else
1521           {
1522             type = tr("media");
1523           }
1524 
1525           enclosureStr.append(QString("<a href=\"%1\" class=\"enclosure\"> %2 %3 </a><p>").
1526                               arg(enclosureUrl, tr("Link to"), type));
1527         }
1528       }
1529 
1530       content = enclosureStr + content;
1531 
1532       bool ltr = !feedsModel_->dataField(feedIndex, "layoutDirection").toInt();
1533       QString cssStr = cssString_.
1534           arg(ltr ? "left" : "right").  // text-align
1535           arg(ltr ? "ltr" : "rtl").    // direction
1536           arg(ltr ? "right" : "left");  // "Date" text-align
1537 
1538       if (!autoLoadImages_) {
1539         QzRegExp reg("<img[^>]+>", Qt::CaseInsensitive);
1540         content = content.remove(reg);
1541       }
1542 
1543       QUrl url;
1544       url.setScheme(newsUrl.scheme());
1545       url.setHost(newsUrl.host());
1546       if (url.host().indexOf('.') == -1) {
1547         QUrl hostUrl = feedsModel_->dataField(feedIndex, "htmlUrl").toString();
1548         url.setHost(hostUrl.host());
1549       }
1550 
1551       if (ltr)
1552         htmlStr = htmlString_.arg(cssStr, titleString, dateString, authorString, content, url.toString());
1553       else
1554         htmlStr = htmlRtlString_.arg(cssStr, titleString, dateString, authorString, content, url.toString());
1555     } else {
1556       if (!autoLoadImages_) {
1557         content = content.remove(QzRegExp("<img[^>]+>", Qt::CaseInsensitive));
1558       }
1559 
1560       htmlStr = content;
1561     }
1562 
1563     htmlStr = htmlStr.replace("src=\"//", "src=\"http://");
1564 
1565     emit signalSetHtmlWebView(htmlStr);
1566   }
1567 }
1568 
loadNewspaper(int refresh)1569 void NewsTabWidget::loadNewspaper(int refresh)
1570 {
1571   if (mainWindow_->newsLayout_ != 1) return;
1572   setWebToolbarVisible(false, false);
1573   webView_->setUpdatesEnabled(false);
1574 
1575   int sortOrder = newsHeader_->sortIndicatorOrder();
1576   int scrollBarValue = 0;
1577   int height = 0;
1578   if (refresh != RefreshAll) {
1579     scrollBarValue = webView_->page()->mainFrame()->scrollBarValue(Qt::Vertical);
1580     height = webView_->page()->mainFrame()->contentsSize().height();
1581   }
1582   webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, true);
1583 
1584   QString htmlStr;
1585   QUrl hostUrl;
1586   bool ltr = true;
1587 
1588   if (type_ == TabTypeFeed) {
1589     QModelIndex feedIndex = feedsProxyModel_->mapToSource(feedsView_->currentIndex());
1590     hostUrl = feedsModel_->dataField(feedIndex, "htmlUrl").toString();
1591     ltr = !feedsModel_->dataField(feedIndex, "layoutDirection").toInt();
1592   }
1593 
1594   if ((refresh == RefreshAll) || (refresh == RefreshWithPos)) {
1595     QString cssStr = cssString_.
1596         arg(ltr ? "left" : "right"). // text-align
1597         arg(ltr ? "ltr" : "rtl"). // direction
1598         arg(ltr ? "right" : "left"); // "Date" text-align
1599     htmlStr = newspaperHeadHtml_.arg(cssStr, hostUrl.toString());
1600 
1601     webView_->setHtml(htmlStr);
1602   }
1603 
1604   int idx = -1;
1605   if ((refresh == RefreshInsert) && (sortOrder == Qt::DescendingOrder))
1606     idx = newsModel_->rowCount();
1607   while (1) {
1608     if ((refresh == RefreshInsert) && (sortOrder == Qt::DescendingOrder)) {
1609       idx--;
1610       if (idx < 0)
1611         break;
1612     } else {
1613       idx++;
1614       if (idx >= newsModel_->rowCount())
1615         break;
1616     }
1617 
1618     QModelIndex index = newsModel_->index(idx, newsModel_->fieldIndex("id"));
1619     QString newsId = newsModel_->dataField(index.row(), "id").toString();
1620 
1621     if (refresh == RefreshInsert) {
1622       QWebElement document = webView_->page()->mainFrame()->documentElement();
1623       QWebElement element = document.findFirst(QString("div[id=newsItem%1]").arg(newsId));
1624       if (!element.isNull()) {
1625         continue;
1626       }
1627     }
1628 
1629     linkNewsString_ = getLinkNews(index.row());
1630     QString linkString = linkNewsString_;
1631 
1632     QString content = newsModel_->dataField(index.row(), "content").toString();
1633     if (!content.contains(QzRegExp("<html(.*)</html>", Qt::CaseInsensitive))) {
1634       QString description = newsModel_->dataField(index.row(), "description").toString();
1635       if (content.isEmpty() || (description.length() > content.length())) {
1636         content = description;
1637       }
1638 
1639       //      QTextDocumentFragment textDocument = QTextDocumentFragment::fromHtml(content);
1640       //      content = textDocument.toPlainText();
1641       //      content = webView_->fontMetrics().elidedText(
1642       //            content, Qt::ElideRight, 1500);
1643 
1644       QString feedId = newsModel_->dataField(index.row(), "feedId").toString();
1645       QModelIndex feedIndex = feedsModel_->indexById(feedId.toInt());
1646 
1647       QString iconStr = "qrc:/images/bulletRead";
1648       QString titleStyle = "read";
1649       if (newsModel_->dataField(index.row(), "new").toInt() == 1) {
1650         iconStr = "qrc:/images/bulletNew";
1651         titleStyle = "unread";
1652       } else if (newsModel_->dataField(index.row(), "read").toInt() == 0) {
1653         iconStr = "qrc:/images/bulletUnread";
1654         titleStyle = "unread";
1655       }
1656       QString readImg = QString("<a href=\"quiterss://read.action.ui?#%1\" title='%3'>"
1657                                 "<img class='quiterss-img' id=\"readAction%1\" src=\"%2\"/></a>").
1658           arg(newsId).arg(iconStr).arg(tr("Mark Read/Unread"));
1659 
1660       QString feedImg;
1661       QByteArray byteArray = feedsModel_->dataField(feedIndex, "image").toByteArray();
1662       if (!byteArray.isEmpty())
1663         feedImg = QString("<img class='quiterss-img' src=\"data:image/png;base64,") % byteArray % "\"/>";
1664       else
1665         feedImg = QString("<img class='quiterss-img' src=\"qrc:/images/feed\"/>");
1666 
1667       QString titleString = newsModel_->dataField(index.row(), "title").toString();
1668       if (!linkString.isEmpty()) {
1669         titleString = QString("<a href='%1' class='%2' id='title%3'>%4</a>").
1670             arg(linkString, titleStyle, newsId, titleString);
1671       }
1672 
1673       QDateTime dtLocal;
1674       QString dateString = newsModel_->dataField(index.row(), "published").toString();
1675       if (!dateString.isNull()) {
1676         QDateTime dtLocalTime = QDateTime::currentDateTime();
1677         QDateTime dtUTC = QDateTime(dtLocalTime.date(), dtLocalTime.time(), Qt::UTC);
1678         int nTimeShift = dtLocalTime.secsTo(dtUTC);
1679 
1680         QDateTime dt = QDateTime::fromString(dateString, Qt::ISODate);
1681         dtLocal = dt.addSecs(nTimeShift);
1682       } else {
1683         dtLocal = QDateTime::fromString(
1684               newsModel_->dataField(index.row(), "received").toString(),
1685               Qt::ISODate);
1686       }
1687       if (QDateTime::currentDateTime().date() <= dtLocal.date())
1688         dateString = dtLocal.toString(mainWindow_->formatTime_);
1689       else
1690         dateString = dtLocal.toString(mainWindow_->formatDate_ + " " + mainWindow_->formatTime_);
1691 
1692       // Create author panel from news author
1693       QString authorString;
1694       QString authorName = newsModel_->dataField(index.row(), "author_name").toString();
1695       QString authorEmail = newsModel_->dataField(index.row(), "author_email").toString();
1696       QString authorUri = newsModel_->dataField(index.row(), "author_uri").toString();
1697 
1698       QzRegExp reg("(^\\S+@\\S+\\.\\S+)", Qt::CaseInsensitive);
1699       int pos = reg.indexIn(authorName);
1700       if (pos > -1) {
1701         authorName.replace(reg.cap(1), QString(" <a href='mailto:%1'>%1</a>").arg(reg.cap(1)));
1702       }
1703       authorString = authorName;
1704 
1705       if (!authorEmail.isEmpty())
1706         authorString.append(QString(" <a href='mailto:%1'>e-mail</a>").arg(authorEmail));
1707       if (!authorUri.isEmpty())
1708         authorString.append(QString(" <a href='%1'>page</a>"). arg(authorUri));
1709 
1710       // If news author is absent, create author panel from feed author
1711       // @note(arhohryakov:2012.01.03) Author is got from current feed, because
1712       //   news is belong to it
1713       if (authorString.isEmpty()) {
1714         authorName  = feedsModel_->dataField(feedIndex, "author_name").toString();
1715         authorEmail = feedsModel_->dataField(feedIndex, "author_email").toString();
1716         authorUri   = feedsModel_->dataField(feedIndex, "author_uri").toString();
1717 
1718         authorString = authorName;
1719         if (!authorEmail.isEmpty())
1720           authorString.append(QString(" <a href='mailto:%1'>e-mail</a>").arg(authorEmail));
1721         if (!authorUri.isEmpty())
1722           authorString.append(QString(" <a href='%1'>page</a>").arg(authorUri));
1723       }
1724 
1725       QString commentsStr;
1726       QString commentsUrl = newsModel_->dataField(index.row(), "comments").toString();
1727       if (!commentsUrl.isEmpty()) {
1728         commentsStr = QString("<a href=\"%1\"> %2</a>").arg(commentsUrl, tr("Comments"));
1729       }
1730 
1731       QString category = newsModel_->dataField(index.row(), "category").toString();
1732 
1733       if (!authorString.isEmpty()) {
1734         authorString = QString(tr("Author: %1")).arg(authorString);
1735         if (!commentsStr.isEmpty())
1736           authorString.append(QString(" | %1").arg(commentsStr));
1737         if (!category.isEmpty())
1738           authorString.append(QString(" | %1").arg(category));
1739       } else {
1740         if (!commentsStr.isEmpty())
1741           authorString.append(commentsStr);
1742         if (!category.isEmpty()) {
1743           if (!commentsStr.isEmpty())
1744             authorString.append(QString(" | %1").arg(category));
1745           else
1746             authorString.append(category);
1747         }
1748       }
1749 
1750       QString labelsString = getHtmlLabels(index.row());
1751       authorString.append(QString("<table class=\"labels\" id=\"labels%1\"><tr>%2</tr></table>").
1752                           arg(newsId).arg(labelsString));
1753 
1754       QString enclosureStr;
1755       QString enclosureUrl = newsModel_->dataField(index.row(), "enclosure_url").toString();
1756       if (!enclosureUrl.isEmpty()) {
1757         QString type = newsModel_->dataField(index.row(), "enclosure_type").toString();
1758         if (type.contains("image")) {
1759           if (!content.contains(enclosureUrl) && autoLoadImages_) {
1760             enclosureStr = QString("<IMG SRC=\"%1\" class=\"enclosureImg\"><p>").
1761                 arg(enclosureUrl);
1762           }
1763         } else {
1764           if (type.contains("audio")) {
1765             type = tr("audio");
1766             enclosureStr = audioPlayerHtml_.arg(enclosureUrl);
1767             enclosureStr.append("<p>");
1768           }
1769           else if (type.contains("video")) {
1770             type = tr("video");
1771             enclosureStr = videoPlayerHtml_.arg(enclosureUrl);
1772             enclosureStr.append("<p>");
1773           }
1774           else type = tr("media");
1775 
1776           enclosureStr.append(QString("<a href=\"%1\" class=\"enclosure\"> %2 %3 </a><p>").
1777                               arg(enclosureUrl, tr("Link to"), type));
1778         }
1779       }
1780 
1781       content = enclosureStr + content;
1782 
1783       if (!autoLoadImages_) {
1784         QzRegExp reg("<img[^>]+>", Qt::CaseInsensitive);
1785         content = content.remove(reg);
1786       }
1787 
1788       iconStr = "qrc:/images/starOff";
1789       if (newsModel_->dataField(index.row(), "starred").toInt() == 1) {
1790         iconStr = "qrc:/images/starOn";
1791       }
1792       QString starAction = QString("<div class=\"star-action\">"
1793                                    "<a href=\"quiterss://star.action.ui?#%1\" title='%3'>"
1794                                    "<img class='quiterss-img' id=\"starAction%1\" src=\"%2\"/></a></div>").
1795           arg(newsId).arg(iconStr).arg(tr("Mark News Star"));
1796       QString labelsMenu = QString("<div class=\"labels-menu\">"
1797                                    "<a href=\"quiterss://labels.menu.ui?#%1\" title='%2'>"
1798                                    "<img class='quiterss-img' id=\"labelsMenu%1\" src=\"qrc:/images/label_5\"/></a></div>").
1799           arg(newsId).arg(tr("Label"));
1800       QString shareMenu = QString("<div class=\"share-menu\">"
1801                                   "<a href=\"quiterss://share.menu.ui?#%1\" title='%2'>"
1802                                   "<img class='quiterss-img' id=\"shareMenu%1\" src=\"qrc:/images/images/share.png\"/></a></div>").
1803           arg(newsId).arg(tr("Share"));
1804       QString openBrowserAction = QString("<div class=\"open-browser\">"
1805                                           "<a href=\"quiterss://open.browser.ui?#%1\" title='%2'>"
1806                                           "<img class='quiterss-img' id=\"openBrowser%1\" src=\"qrc:/images/openBrowser\"'/></a></div>").
1807           arg(newsId).arg(tr("Open News in External Browser"));
1808       QString deleteAction = QString("<div class=\"delete-action\">"
1809                                      "<a href=\"quiterss://delete.action.ui?#%1\" title='%2'>"
1810                                      "<img class='quiterss-img' id=\"deleteAction%1\" src=\"qrc:/images/delete\"/></a></div>").
1811           arg(newsId).arg(tr("Delete"));
1812       QString actionNews = starAction % labelsMenu % shareMenu % openBrowserAction %
1813           deleteAction;
1814 
1815       QString border = "1";
1816       if (idx + 1 == newsModel_->rowCount())
1817         border = "0";
1818       if (ltr) {
1819         htmlStr = newspaperHtml_.arg(newsId, border, readImg, feedImg, titleString,
1820                                      dateString, authorString, content, actionNews);
1821       } else {
1822         htmlStr = newspaperHtmlRtl_.arg(newsId, border, readImg, feedImg, titleString,
1823                                         dateString, authorString, content, actionNews);
1824       }
1825     } else {
1826       if (!autoLoadImages_) {
1827         content = content.remove(QzRegExp("<img[^>]+>", Qt::CaseInsensitive));
1828       }
1829       htmlStr = content;
1830     }
1831 
1832     htmlStr = htmlStr.replace("src=\"//", "src=\"http://");
1833 
1834     QWebElement document = webView_->page()->mainFrame()->documentElement();
1835     QWebElement element = document.findFirst("body");
1836     if ((refresh == RefreshInsert) && (sortOrder == Qt::DescendingOrder))
1837       element.prependInside(htmlStr);
1838     else
1839       element.appendInside(htmlStr);
1840     qApp->processEvents();
1841   }
1842 
1843   webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages_);
1844   if ((refresh == RefreshInsert) && (sortOrder == Qt::DescendingOrder))
1845     scrollBarValue += webView_->page()->mainFrame()->contentsSize().height() - height;
1846   if (refresh != RefreshAll)
1847     webView_->page()->mainFrame()->setScrollBarValue(Qt::Vertical, scrollBarValue);
1848 
1849   webView_->setUpdatesEnabled(true);
1850 }
1851 
1852 /** @brief Asynchorous update web view
1853  *----------------------------------------------------------------------------*/
slotSetHtmlWebView(const QString & html)1854 void NewsTabWidget::slotSetHtmlWebView(const QString &html)
1855 {
1856   webView_->history()->setMaximumItemCount(0);
1857   webView_->setHtml(html);
1858   webView_->history()->setMaximumItemCount(100);
1859 }
1860 
hideWebContent()1861 void NewsTabWidget::hideWebContent()
1862 {
1863   if (mainWindow_->newsLayout_ == 1) return;
1864 
1865   emit signalSetHtmlWebView();
1866   setWebToolbarVisible(false, false);
1867 }
1868 
slotLinkClicked(QUrl url)1869 void NewsTabWidget::slotLinkClicked(QUrl url)
1870 {
1871   if (url.scheme() == QLatin1String("quiterss")) {
1872     actionNewspaper(url);
1873     return;
1874   }
1875 
1876   if (url.scheme() == QLatin1String("mailto")) {
1877     QDesktopServices::openUrl(url);
1878     return;
1879   }
1880 
1881   if (type_ != TabTypeWeb) {
1882     if ((url.host().isEmpty() || (QUrl(url).host().indexOf('.') == -1)) && newsView_->currentIndex().isValid()) {
1883       int row = newsView_->currentIndex().row();
1884       int feedId = newsModel_->dataField(row, "feedId").toInt();
1885       QModelIndex feedIndex = feedsModel_->indexById(feedId);
1886       QUrl hostUrl = feedsModel_->dataField(feedIndex, "htmlUrl").toString();
1887 
1888       url.setScheme(hostUrl.scheme());
1889       url.setHost(hostUrl.host());
1890     }
1891   }
1892 
1893   if ((mainWindow_->externalBrowserOn_ <= 0) &&
1894       (webView_->buttonClick_ != LEFT_BUTTON_ALT)) {
1895     if (webView_->buttonClick_ == LEFT_BUTTON) {
1896       if (!webControlPanel_->isVisible()) {
1897         locationBar_->setText(url.toString());
1898         setWebToolbarVisible(true, false);
1899       }
1900       webView_->load(url);
1901     } else {
1902       if ((webView_->buttonClick_ == MIDDLE_BUTTON) ||
1903           (webView_->buttonClick_ == LEFT_BUTTON_CTRL)) {
1904         mainWindow_->openNewsTab_ = NEW_TAB_BACKGROUND;
1905       } else {
1906         mainWindow_->openNewsTab_ = NEW_TAB_FOREGROUND;
1907       }
1908       if (!mainWindow_->openLinkInBackgroundEmbedded_) {
1909         if (mainWindow_->openNewsTab_ == NEW_TAB_BACKGROUND)
1910           mainWindow_->openNewsTab_ = NEW_TAB_FOREGROUND;
1911         else
1912           mainWindow_->openNewsTab_ = NEW_TAB_BACKGROUND;
1913       }
1914 
1915       mainWindow_->createWebTab(url);
1916     }
1917   } else {
1918     openUrl(url);
1919   }
1920 
1921   webView_->buttonClick_ = 0;
1922 }
1923 //----------------------------------------------------------------------------
slotLinkHovered(const QString & link,const QString &,const QString &)1924 void NewsTabWidget::slotLinkHovered(const QString &link, const QString &, const QString &)
1925 {
1926   if (QUrl(link).scheme() == QLatin1String("quiterss")) return;
1927 
1928   mainWindow_->statusBar()->showMessage(link.simplified(), 3000);
1929 }
1930 //----------------------------------------------------------------------------
slotSetValue(int value)1931 void NewsTabWidget::slotSetValue(int value)
1932 {
1933   emit loadProgress(value);
1934   QString str = QString(" %1 kB / %2 kB").
1935       arg(webView_->page()->bytesReceived()/1000).
1936       arg(webView_->page()->totalBytes()/1000);
1937   webViewProgressLabel_->setText(str);
1938 }
1939 //----------------------------------------------------------------------------
slotLoadStarted()1940 void NewsTabWidget::slotLoadStarted()
1941 {
1942   if (type_ == TabTypeWeb) {
1943     newsIconTitle_->setMovie(newsIconMovie_);
1944     newsIconMovie_->start();
1945   }
1946 
1947   webViewProgress_->setValue(0);
1948   webViewProgress_->show();
1949 }
1950 //----------------------------------------------------------------------------
slotLoadFinished(bool)1951 void NewsTabWidget::slotLoadFinished(bool)
1952 {
1953   if (type_ == TabTypeWeb) {
1954     newsIconMovie_->stop();
1955     QPixmap iconTab;
1956     iconTab.load(":/images/webPage");
1957     newsIconTitle_->setPixmap(iconTab);
1958   }
1959 
1960   webViewProgress_->hide();
1961 }
1962 
slotUrlEnter()1963 void NewsTabWidget::slotUrlEnter()
1964 {
1965   webView_->setFocus();
1966 
1967   if (!locationBar_->text().startsWith("http://") &&
1968       !locationBar_->text().startsWith("https://")) {
1969     locationBar_->setText("http://" + locationBar_->text());
1970   }
1971   locationBar_->setCursorPosition(0);
1972 
1973   webView_->load(QUrl(locationBar_->text()));
1974 }
1975 
slotUrlChanged(const QUrl & url)1976 void NewsTabWidget::slotUrlChanged(const QUrl &url)
1977 {
1978   locationBar_->setText(url.toString());
1979   locationBar_->setCursorPosition(0);
1980 }
1981 
1982 /** @brief Go to short news content
1983  *----------------------------------------------------------------------------*/
webHomePage()1984 void NewsTabWidget::webHomePage()
1985 {
1986   if (type_ != TabTypeWeb) {
1987     switch (mainWindow_->newsLayout_) {
1988     case 1:
1989       loadNewspaper();
1990       break;
1991     default:
1992       updateWebView(newsView_->currentIndex());
1993     }
1994   } else {
1995     webView_->history()->goToItem(webView_->history()->itemAt(0));
1996   }
1997 }
1998 
1999 /** @brief Open current web page in external browser
2000  *----------------------------------------------------------------------------*/
openPageInExternalBrowser()2001 void NewsTabWidget::openPageInExternalBrowser()
2002 {
2003   openUrl(webView_->url());
2004 }
2005 
2006 /** @brief Open news in browser
2007  *----------------------------------------------------------------------------*/
openInBrowserNews()2008 void NewsTabWidget::openInBrowserNews()
2009 {
2010   if (type_ >= TabTypeWeb) return;
2011 
2012   int externalBrowserOn_ = mainWindow_->externalBrowserOn_;
2013   mainWindow_->externalBrowserOn_ = 0;
2014   slotNewsViewDoubleClicked(newsView_->currentIndex());
2015   mainWindow_->externalBrowserOn_ = externalBrowserOn_;
2016 }
2017 
2018 /** @brief Open news in external browser
2019  *----------------------------------------------------------------------------*/
openInExternalBrowserNews()2020 void NewsTabWidget::openInExternalBrowserNews()
2021 {
2022   if (type_ == TabTypeDownloads) return;
2023 
2024   if (type_ != TabTypeWeb) {
2025     QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(0);
2026     QStringList feedIdList;
2027 
2028     int cnt = indexes.count();
2029     if (cnt == 0) return;
2030 
2031     for (int i = cnt-1; i >= 0; --i) {
2032       QSqlQuery q;
2033       QModelIndex curIndex = indexes.at(i);
2034       if (newsModel_->dataField(curIndex.row(), "read").toInt() == 0) {
2035         newsModel_->setData(
2036               newsModel_->index(curIndex.row(), newsModel_->fieldIndex("new")),
2037               0);
2038         newsModel_->setData(
2039               newsModel_->index(curIndex.row(), newsModel_->fieldIndex("read")),
2040               1);
2041 
2042         int newsId = newsModel_->dataField(curIndex.row(), "id").toInt();
2043         q.exec(QString("UPDATE news SET new=0, read=1 WHERE id=='%2'").arg(newsId));
2044         QString feedId = newsModel_->dataField(curIndex.row(), "feedId").toString();
2045         if (!feedIdList.contains(feedId)) feedIdList.append(feedId);
2046       }
2047 
2048       QUrl url = QUrl::fromEncoded(getLinkNews(indexes.at(i).row()).toUtf8());
2049       if (url.host().isEmpty() || (QUrl(url).host().indexOf('.') == -1)) {
2050         QString feedId = newsModel_->dataField(indexes.at(i).row(), "feedId").toString();
2051         QModelIndex feedIndex = feedsModel_->indexById(feedId.toInt());
2052         QUrl hostUrl = feedsModel_->dataField(feedIndex, "htmlUrl").toString();
2053 
2054         url.setScheme(hostUrl.scheme());
2055         url.setHost(hostUrl.host());
2056       }
2057 
2058       openUrl(url);
2059     }
2060 
2061     if (!feedIdList.isEmpty()) {
2062       foreach (QString feedId, feedIdList) {
2063         mainWindow_->slotUpdateStatus(feedId.toInt());
2064       }
2065       mainWindow_->recountCategoryCounts();
2066       newsView_->viewport()->update();
2067     }
2068   } else {
2069     openUrl(webView_->url());
2070   }
2071 }
2072 
setNewsLayout()2073 void NewsTabWidget::setNewsLayout()
2074 {
2075   if (type_ >= TabTypeWeb) return;
2076 
2077   switch (mainWindow_->newsLayout_) {
2078   case 1:
2079     newsWidget_->setVisible(false);
2080     loadNewspaper();
2081     break;
2082   default:
2083     newsWidget_->setVisible(true);
2084     updateWebView(newsView_->currentIndex());
2085   }
2086 }
2087 
2088 /** @brief Set browser position
2089  *----------------------------------------------------------------------------*/
setBrowserPosition()2090 void NewsTabWidget::setBrowserPosition()
2091 {
2092   if (type_ >= TabTypeWeb) return;
2093 
2094   int idx = newsTabWidgetSplitter_->indexOf(webWidget_);
2095 
2096   switch (mainWindow_->browserPosition_) {
2097   case TOP_POSITION: case LEFT_POSITION:
2098     newsTabWidgetSplitter_->insertWidget(0, newsTabWidgetSplitter_->widget(idx));
2099     break;
2100   default:
2101     newsTabWidgetSplitter_->insertWidget(1, newsTabWidgetSplitter_->widget(idx));
2102   }
2103 
2104   switch (mainWindow_->browserPosition_) {
2105   case RIGHT_POSITION: case LEFT_POSITION:
2106     newsTabWidgetSplitter_->setOrientation(Qt::Horizontal);
2107     newsTabWidgetSplitter_->setStyleSheet(
2108           QString("QSplitter::handle {background: qlineargradient("
2109                   "x1: 0, y1: 0, x2: 0, y2: 1,"
2110                   "stop: 0 %1, stop: 0.07 %2);}").
2111           arg(newsPanelWidget_->palette().background().color().name()).
2112           arg(qApp->palette().color(QPalette::Dark).name()));
2113     break;
2114   default:
2115     newsTabWidgetSplitter_->setOrientation(Qt::Vertical);
2116     newsTabWidgetSplitter_->setStyleSheet(
2117           QString("QSplitter::handle {background: %1; margin-top: 1px; margin-bottom: 1px;}").
2118           arg(qApp->palette().color(QPalette::Dark).name()));
2119   }
2120 
2121   newsTabWidgetSplitter_->setChildrenCollapsible(false);
2122 }
2123 
2124 /** @brief Close tab while press X-button
2125  *----------------------------------------------------------------------------*/
slotTabClose()2126 void NewsTabWidget::slotTabClose()
2127 {
2128   mainWindow_->slotCloseTab(mainWindow_->stackedWidget_->indexOf(this));
2129 }
2130 
2131 /** @brief Display browser open page title on tab
2132  *----------------------------------------------------------------------------*/
webTitleChanged(QString title)2133 void NewsTabWidget::webTitleChanged(QString title)
2134 {
2135   if ((type_ == TabTypeWeb) && !title.isEmpty()) {
2136     setTextTab(title);
2137   }
2138 }
2139 
2140 /** @brief Open news in new tab
2141  *----------------------------------------------------------------------------*/
openNewsNewTab()2142 void NewsTabWidget::openNewsNewTab()
2143 {
2144   if (type_ >= TabTypeWeb) return;
2145 
2146   QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(0);
2147 
2148   int cnt = indexes.count();
2149   if (cnt == 0) return;
2150 
2151   for (int i = cnt-1; i >= 0; --i) {
2152     QModelIndex index = indexes.at(i);
2153     int row = index.row();
2154     if (mainWindow_->markNewsReadOn_ && mainWindow_->markCurNewsRead_)
2155       slotSetItemRead(index, 1);
2156 
2157     QUrl url = QUrl::fromEncoded(getLinkNews(row).toUtf8());
2158     if (url.host().isEmpty() || (QUrl(url).host().indexOf('.') == -1)) {
2159       int feedId = newsModel_->dataField(row, "feedId").toInt();
2160       QModelIndex feedIndex = feedsModel_->indexById(feedId);
2161       QUrl hostUrl = feedsModel_->dataField(feedIndex, "htmlUrl").toString();
2162 
2163       url.setScheme(hostUrl.scheme());
2164       url.setHost(hostUrl.host());
2165     }
2166 
2167     mainWindow_->createWebTab(url);
2168   }
2169 }
2170 
2171 /** @brief Open link
2172  *----------------------------------------------------------------------------*/
openLink()2173 void NewsTabWidget::openLink()
2174 {
2175   slotLinkClicked(linkUrl_);
2176 }
2177 
2178 /** @brief Open link in new tab
2179  *----------------------------------------------------------------------------*/
openLinkInNewTab()2180 void NewsTabWidget::openLinkInNewTab()
2181 {
2182   int externalBrowserOn_ = mainWindow_->externalBrowserOn_;
2183   mainWindow_->externalBrowserOn_ = 0;
2184 
2185   if (QApplication::keyboardModifiers() == Qt::NoModifier) {
2186     webView_->buttonClick_ = MIDDLE_BUTTON;
2187   } else {
2188     webView_->buttonClick_ = MIDDLE_BUTTON_MOD;
2189   }
2190 
2191   slotLinkClicked(linkUrl_);
2192   mainWindow_->externalBrowserOn_ = externalBrowserOn_;
2193 }
2194 
2195 /** @brief Open link in browser
2196  *----------------------------------------------------------------------------*/
openUrl(const QUrl & url)2197 bool NewsTabWidget::openUrl(const QUrl &url)
2198 {
2199   if (!url.isValid())
2200     return false;
2201 
2202   if (url.scheme() == QLatin1String("mailto"))
2203     return QDesktopServices::openUrl(url);
2204 
2205   mainWindow_->isOpeningLink_ = true;
2206   if ((mainWindow_->externalBrowserOn_ == 2) || (mainWindow_->externalBrowserOn_ == -1)) {
2207 #if defined(Q_OS_WIN)
2208     quintptr returnValue = (quintptr)ShellExecute(
2209           0, 0,
2210           (wchar_t *)QString::fromUtf8(mainWindow_->externalBrowser_.toUtf8()).utf16(),
2211           (wchar_t *)QString::fromUtf8(url.toEncoded().constData()).utf16(),
2212           0, SW_SHOWNORMAL);
2213     if (returnValue > 32)
2214       return true;
2215 #elif defined(Q_OS_MAC)
2216     return (QProcess::startDetached("open", QStringList() << "-a" <<
2217                                     QString::fromUtf8(mainWindow_->externalBrowser_.toUtf8()) <<
2218                                     QString::fromUtf8(url.toEncoded().constData())));
2219 #else
2220     return (QProcess::startDetached(QString::fromUtf8(mainWindow_->externalBrowser_.toUtf8()) + QLatin1Char(' ') +
2221                                     QString::fromUtf8(url.toEncoded().constData())));
2222 #endif
2223   }
2224   return QDesktopServices::openUrl(url);
2225 }
2226 //----------------------------------------------------------------------------
slotFindText(const QString & text)2227 void NewsTabWidget::slotFindText(const QString &text)
2228 {
2229   QString objectName = findText_->findGroup_->checkedAction()->objectName();
2230   if (objectName == "findInBrowserAct") {
2231     webView_->findText("", QWebPage::HighlightAllOccurrences);
2232     webView_->findText(text, QWebPage::HighlightAllOccurrences);
2233   } else {
2234     int newsId = newsModel_->dataField(newsView_->currentIndex().row(), "id").toInt();
2235 
2236     QString filterStr;
2237     switch (type_) {
2238     case TabTypeUnread:
2239     case TabTypeStar:
2240     case TabTypeDel:
2241     case TabTypeLabel:
2242       filterStr = categoryFilterStr_;
2243       break;
2244     default:
2245       filterStr = mainWindow_->newsFilterStr;
2246     }
2247 
2248     if (!text.isEmpty()) {
2249       QString findText = text;
2250       findText = findText.replace("'", "''").toUpper();
2251       if (objectName == "findTitleAct") {
2252         filterStr.append(
2253               QString(" AND UPPER(title) LIKE '%%1%'").arg(findText));
2254       } else if (objectName == "findAuthorAct") {
2255         filterStr.append(
2256               QString(" AND UPPER(author_name) LIKE '%%1%'").arg(findText));
2257       } else if (objectName == "findCategoryAct") {
2258         filterStr.append(
2259               QString(" AND UPPER(category) LIKE '%%1%'").arg(findText));
2260       } else if (objectName == "findContentAct") {
2261         filterStr.append(
2262               QString(" AND (UPPER(content) LIKE '%%1%' OR UPPER(description) LIKE '%%1%')").
2263               arg(findText));
2264       } else if (objectName == "findLinkAct") {
2265         filterStr.append(
2266               QString(" AND link_href LIKE '%%1%'").
2267               arg(findText));
2268       } else {
2269         filterStr.append(
2270               QString(" AND (UPPER(title) LIKE '%%1%' OR UPPER(author_name) LIKE '%%1%' "
2271                       "OR UPPER(category) LIKE '%%1%' OR UPPER(content) LIKE '%%1%' "
2272                       "OR UPPER(description) LIKE '%%1%')").
2273               arg(findText));
2274       }
2275     }
2276 
2277     newsModel_->setFilter(filterStr);
2278 
2279     QModelIndex index = newsModel_->index(0, newsModel_->fieldIndex("id"));
2280     QModelIndexList indexList = newsModel_->match(index, Qt::EditRole, newsId);
2281     if (indexList.count()) {
2282       int newsRow = indexList.first().row();
2283       newsView_->setCurrentIndex(newsModel_->index(newsRow, newsModel_->fieldIndex("title")));
2284     } else {
2285       currentNewsIdOld = newsId;
2286       hideWebContent();
2287     }
2288   }
2289 }
2290 //----------------------------------------------------------------------------
slotSelectFind()2291 void NewsTabWidget::slotSelectFind()
2292 {
2293   webView_->findText("", QWebPage::HighlightAllOccurrences);
2294   slotFindText(findText_->text());
2295 }
2296 //----------------------------------------------------------------------------
showContextWebPage(const QPoint & p)2297 void NewsTabWidget::showContextWebPage(const QPoint &p)
2298 {
2299   QMenu menu;
2300   QMenu *pageMenu = webView_->page()->createStandardContextMenu();
2301   if (pageMenu) {
2302     menu.addActions(pageMenu->actions());
2303 
2304     webView_->page()->action(QWebPage::OpenLink)->setText(tr("Open Link"));
2305     webView_->page()->action(QWebPage::OpenLinkInNewWindow)->setText(tr("Open in New Tab"));
2306     webView_->page()->action(QWebPage::DownloadLinkToDisk)->setText(tr("Save Link..."));
2307     webView_->page()->action(QWebPage::DownloadImageToDisk)->setText(tr("Save Image..."));
2308     webView_->page()->action(QWebPage::CopyLinkToClipboard)->setText(tr("Copy Link"));
2309     webView_->page()->action(QWebPage::Copy)->setText(tr("Copy"));
2310     webView_->page()->action(QWebPage::Back)->setText(tr("Go Back"));
2311     webView_->page()->action(QWebPage::Forward)->setText(tr("Go Forward"));
2312     webView_->page()->action(QWebPage::Stop)->setText(tr("Stop"));
2313     webView_->page()->action(QWebPage::Reload)->setText(tr("Reload"));
2314     webView_->page()->action(QWebPage::CopyImageToClipboard)->setText(tr("Copy Image"));
2315 #if QT_VERSION >= 0x040800
2316     webView_->page()->action(QWebPage::CopyImageUrlToClipboard)->setText(tr("Copy Image Address"));
2317 #endif
2318 
2319     const QWebHitTestResult &hitTest = webView_->page()->mainFrame()->hitTestContent(p);
2320     if (!hitTest.linkUrl().isEmpty() && hitTest.linkUrl().scheme() != "javascript") {
2321       linkUrl_ = hitTest.linkUrl();
2322       if (mainWindow_->externalBrowserOn_ <= 0) {
2323         menu.addSeparator();
2324         menu.addAction(urlExternalBrowserAct_);
2325       }
2326     } else if (pageMenu->actions().indexOf(webView_->pageAction(QWebPage::Reload)) >= 0) {
2327       if (webView_->title() == "news_descriptions") {
2328         webView_->pageAction(QWebPage::Reload)->setVisible(false);
2329       } else {
2330         webView_->pageAction(QWebPage::Reload)->setVisible(true);
2331         menu.addSeparator();
2332       }
2333       menu.addAction(mainWindow_->autoLoadImagesToggle_);
2334       menu.addSeparator();
2335       menu.addAction(mainWindow_->printAct_);
2336       menu.addAction(mainWindow_->printPreviewAct_);
2337       menu.addSeparator();
2338       menu.addAction(mainWindow_->savePageAsAct_);
2339     } else if (hitTest.isContentEditable()) {
2340       for (int i = 0; i < menu.actions().count(); i++) {
2341         if ((i <= 1) && (menu.actions().at(i)->text() == "Direction")) {
2342           menu.actions().at(i)->setVisible(false);
2343           break;
2344         }
2345       }
2346       menu.insertSeparator(menu.actions().at(0));
2347       menu.insertAction(menu.actions().at(0), webView_->pageAction(QWebPage::Redo));
2348       menu.insertAction(menu.actions().at(0), webView_->pageAction(QWebPage::Undo));
2349     }
2350 
2351     if (!hitTest.isContentEditable() && !hitTest.isContentSelected()) {
2352       menu.addSeparator();
2353       menu.addAction(mainWindow_->adBlockIcon()->menuAction());
2354     }
2355 
2356     menu.exec(webView_->mapToGlobal(p));
2357   }
2358 }
2359 
2360 /** @brief Open link in external browser
2361  *----------------------------------------------------------------------------*/
openUrlInExternalBrowser()2362 void NewsTabWidget::openUrlInExternalBrowser()
2363 {
2364   if (linkUrl_.scheme() == QLatin1String("mailto")) {
2365     QDesktopServices::openUrl(linkUrl_);
2366     return;
2367   }
2368 
2369   if (type_ != TabTypeWeb) {
2370     if (linkUrl_.host().isEmpty() && newsView_->currentIndex().isValid()) {
2371       int row = newsView_->currentIndex().row();
2372       int feedId = newsModel_->dataField(row, "feedId").toInt();
2373       QModelIndex feedIndex = feedsModel_->indexById(feedId);
2374       QUrl hostUrl = feedsModel_->dataField(feedIndex, "htmlUrl").toString();
2375 
2376       linkUrl_.setScheme(hostUrl.scheme());
2377       linkUrl_.setHost(hostUrl.host());
2378     }
2379   }
2380   openUrl(linkUrl_);
2381 }
2382 
setWebToolbarVisible(bool show,bool checked)2383 void NewsTabWidget::setWebToolbarVisible(bool show, bool checked)
2384 {
2385   if (!checked) webToolbarShow_ = show;
2386   webControlPanel_->setVisible(webToolbarShow_ &
2387                                mainWindow_->browserToolbarToggle_->isChecked());
2388 
2389 }
2390 
2391 /** @brief Set label for selected news
2392  *----------------------------------------------------------------------------*/
setLabelNews(int labelId)2393 void NewsTabWidget::setLabelNews(int labelId)
2394 {
2395   if (type_ >= TabTypeWeb) return;
2396 
2397   QList<QModelIndex> indexes = newsView_->selectionModel()->selectedRows(
2398         newsModel_->fieldIndex("label"));
2399 
2400   int cnt = indexes.count();
2401   if (cnt == 0) return;
2402 
2403   if (cnt == 1) {
2404     QModelIndex index = indexes.at(0);
2405     QString strIdLabels = index.data(Qt::EditRole).toString();
2406     if (!strIdLabels.contains(QString(",%1,").arg(labelId))) {
2407       if (strIdLabels.isEmpty()) strIdLabels.append(",");
2408       strIdLabels.append(QString::number(labelId));
2409       strIdLabels.append(",");
2410     } else {
2411       strIdLabels.replace(QString(",%1,").arg(labelId), ",");
2412     }
2413     newsModel_->setData(index, strIdLabels);
2414 
2415     int newsId = newsModel_->dataField(index.row(), "id").toInt();
2416 
2417     if ((newsId == currentNewsIdOld) &&
2418         (webView_->title() == "news_descriptions")) {
2419       QWebFrame *frame = webView_->page()->mainFrame();
2420       QWebElement document = frame->documentElement();
2421       QWebElement element = document.findFirst(QString("table[id=labels%1]").arg(newsId));
2422       if (!element.isNull()) {
2423         webView_->settings()->setAttribute(QWebSettings::AutoLoadImages,true);
2424         element.removeAllChildren();
2425         QString labelsString = getHtmlLabels(index.row());
2426         element.appendInside(labelsString);
2427         webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages_);
2428       }
2429     }
2430 
2431     QSqlQuery q;
2432     q.exec(QString("UPDATE news SET label='%1' WHERE id=='%2'").
2433            arg(strIdLabels).arg(newsId));
2434     if (newsId != currentNewsIdOld) {
2435       newsView_->selectionModel()->select(
2436             index, QItemSelectionModel::Deselect|QItemSelectionModel::Rows);
2437     }
2438   } else {
2439     bool setLabel = false;
2440     for (int i = cnt-1; i >= 0; --i) {
2441       QModelIndex index = indexes.at(i);
2442       QString strIdLabels = index.data(Qt::EditRole).toString();
2443       if (!strIdLabels.contains(QString(",%1,").arg(labelId))) {
2444         setLabel = true;
2445         break;
2446       }
2447     }
2448 
2449     db_.transaction();
2450     for (int i = cnt-1; i >= 0; --i) {
2451       QModelIndex index = indexes.at(i);
2452       QString strIdLabels = index.data(Qt::EditRole).toString();
2453       if (setLabel) {
2454         if (strIdLabels.contains(QString(",%1,").arg(labelId))) continue;
2455         if (strIdLabels.isEmpty()) strIdLabels.append(",");
2456         strIdLabels.append(QString::number(labelId));
2457         strIdLabels.append(",");
2458       } else {
2459         strIdLabels.replace(QString(",%1,").arg(labelId), ",");
2460       }
2461       newsModel_->setData(index, strIdLabels);
2462 
2463       int newsId = newsModel_->dataField(index.row(), "id").toInt();
2464 
2465       if ((newsId == currentNewsIdOld) &&
2466           (webView_->title() == "news_descriptions")) {
2467         QWebFrame *frame = webView_->page()->mainFrame();
2468         QWebElement document = frame->documentElement();
2469         QWebElement element = document.findFirst(QString("table[id=labels%1]").arg(newsId));
2470         if (!element.isNull()) {
2471           element.removeAllChildren();
2472           QString labelsString = getHtmlLabels(index.row());
2473           element.appendInside(labelsString);
2474         }
2475       }
2476 
2477       QSqlQuery q;
2478       q.exec(QString("UPDATE news SET label='%1' WHERE id=='%2'").
2479              arg(strIdLabels).arg(newsId));
2480       if (newsId != currentNewsIdOld) {
2481         newsView_->selectionModel()->select(
2482               index, QItemSelectionModel::Deselect|QItemSelectionModel::Rows);
2483       }
2484     }
2485     db_.commit();
2486   }
2487   newsView_->viewport()->update();
2488   mainWindow_->recountCategoryCounts();
2489 }
2490 
slotNewslLabelClicked(QModelIndex index)2491 void NewsTabWidget::slotNewslLabelClicked(QModelIndex index)
2492 {
2493   if (!newsView_->selectionModel()->isSelected(index)) {
2494     newsView_->selectionModel()->clearSelection();
2495     newsView_->selectionModel()->select(
2496           index, QItemSelectionModel::Select|QItemSelectionModel::Rows);
2497   }
2498   mainWindow_->newsLabelMenu_->popup(
2499         newsView_->viewport()->mapToGlobal(newsView_->visualRect(index).bottomLeft()));
2500 }
2501 
showLabelsMenu()2502 void NewsTabWidget::showLabelsMenu()
2503 {
2504   if (type_ >= TabTypeWeb) return;
2505   if (!newsView_->currentIndex().isValid()) return;
2506 
2507   for (int i = newsHeader_->count()-1; i >= 0; i--) {
2508     int lIdx = newsHeader_->logicalIndex(i);
2509     if (!newsHeader_->isSectionHidden(lIdx)) {
2510       int row = newsView_->currentIndex().row();
2511       slotNewslLabelClicked(newsModel_->index(row, lIdx));
2512       break;
2513     }
2514   }
2515 }
2516 
reduceNewsList()2517 void NewsTabWidget::reduceNewsList()
2518 {
2519   if (type_ >= TabTypeWeb) return;
2520 
2521   QList <int> sizes = newsTabWidgetSplitter_->sizes();
2522   sizes.insert(0, sizes.takeAt(0) - RESIZESTEP);
2523   newsTabWidgetSplitter_->setSizes(sizes);
2524 }
2525 
increaseNewsList()2526 void NewsTabWidget::increaseNewsList()
2527 {
2528   if (type_ >= TabTypeWeb) return;
2529 
2530   QList <int> sizes = newsTabWidgetSplitter_->sizes();
2531   sizes.insert(0, sizes.takeAt(0) + RESIZESTEP);
2532   newsTabWidgetSplitter_->setSizes(sizes);
2533 }
2534 
2535 /** @brief Search unread news
2536  * @param next search condition: true - search next, else - previous
2537  *----------------------------------------------------------------------------*/
findUnreadNews(bool next)2538 int NewsTabWidget::findUnreadNews(bool next)
2539 {
2540   int newsRow = -1;
2541 
2542   int newsRowCur = newsView_->currentIndex().row();
2543   QModelIndex index;
2544   QModelIndexList indexList;
2545   if (next) {
2546     index = newsModel_->index(newsRowCur+1, newsModel_->fieldIndex("read"));
2547     indexList = newsModel_->match(index, Qt::EditRole, 0);
2548     if (indexList.isEmpty()) {
2549       index = newsModel_->index(0, newsModel_->fieldIndex("read"));
2550       indexList = newsModel_->match(index, Qt::EditRole, 0);
2551     }
2552   } else {
2553     index = newsModel_->index(newsRowCur, newsModel_->fieldIndex("read"));
2554     indexList = newsModel_->match(index, Qt::EditRole, 0, -1);
2555   }
2556   if (!indexList.isEmpty()) newsRow = indexList.last().row();
2557 
2558   return newsRow;
2559 }
2560 
2561 /** @brief Set tab title
2562  *----------------------------------------------------------------------------*/
setTextTab(const QString & text)2563 void NewsTabWidget::setTextTab(const QString &text)
2564 {
2565   int padding = 15;
2566 
2567   if (closeButton_->isHidden())
2568     padding = 0;
2569 
2570   QString textTab = newsTextTitle_->fontMetrics().elidedText(
2571         text, Qt::ElideRight, newsTitleLabel_->width() - 16 - 3 - padding);
2572   newsTextTitle_->setText(textTab);
2573   newsTitleLabel_->setToolTip(text);
2574 
2575   emit signalSetTextTab(text, this);
2576 }
2577 
2578 /** @brief Share news
2579  *----------------------------------------------------------------------------*/
slotShareNews(QAction * action)2580 void NewsTabWidget::slotShareNews(QAction *action)
2581 {
2582   bool externalApp = false;
2583 
2584   QList<QModelIndex> indexes;
2585   int cnt = 0;
2586   if (type_ < TabTypeWeb) {
2587     indexes = newsView_->selectionModel()->selectedRows(0);
2588     cnt = indexes.count();
2589   } else if (type_ == TabTypeWeb) {
2590     cnt = 1;
2591   }
2592   if (cnt == 0) return;
2593 
2594   for (int i = cnt-1; i >= 0; --i) {
2595     QString title;
2596     QString linkString;
2597     QString content;
2598     if (type_ < TabTypeWeb) {
2599       title = newsModel_->dataField(indexes.at(i).row(), "title").toString();
2600       linkString = getLinkNews(indexes.at(i).row());
2601 
2602       content = newsModel_->dataField(indexes.at(i).row(), "content").toString();
2603       QString description = newsModel_->dataField(indexes.at(i).row(), "description").toString();
2604       if (content.isEmpty() || (description.length() > content.length())) {
2605         content = description;
2606       }
2607       QTextDocumentFragment textDocument = QTextDocumentFragment::fromHtml(content);
2608       content = textDocument.toPlainText();
2609     } else {
2610       title = webView_->title();
2611       linkString = webView_->url().toString();
2612       content = webView_->page()->mainFrame()->toPlainText();
2613     }
2614 #if defined(Q_OS_WIN) || defined(Q_OS_OS2) || defined(Q_OS_MAC)
2615     content = content.replace("\n", "%0A");
2616     content = content.replace("\"", "%22");
2617 #endif
2618 
2619     QUrl url;
2620     if (action->objectName() == "emailShareAct") {
2621       url.setUrl("mailto:");
2622 #ifdef HAVE_QT5
2623       QUrlQuery urlQuery;
2624       urlQuery.addQueryItem("subject", title);
2625       urlQuery.addQueryItem("body", linkString);
2626       //#if defined(Q_OS_WIN) || defined(Q_OS_OS2) || defined(Q_OS_MAC)
2627       //      urlQuery.addQueryItem("body", linkString + "%0A%0A" + content);
2628       //#else
2629       //      urlQuery.addQueryItem("body", linkString + "\n\n" + content);
2630       //#endif
2631       url.setQuery(urlQuery);
2632 #else
2633       url.addQueryItem("subject", title);
2634 #if defined(Q_OS_WIN) || defined(Q_OS_OS2) || defined(Q_OS_MAC)
2635       url.addQueryItem("body", linkString + "%0A%0A" + content);
2636 #else
2637       url.addQueryItem("body", linkString + "\n\n" + content);
2638 #endif
2639 #endif
2640       externalApp = true;
2641     } else if (action->objectName() == "evernoteShareAct") {
2642       url.setUrl("https://www.evernote.com/clip.action");
2643 #ifdef HAVE_QT5
2644       QUrlQuery urlQuery;
2645       urlQuery.addQueryItem("url", linkString);
2646       urlQuery.addQueryItem("title", title);
2647       url.setQuery(urlQuery);
2648 #else
2649       url.addQueryItem("url", linkString);
2650       url.addQueryItem("title", title);
2651 #endif
2652     } else if (action->objectName() == "facebookShareAct") {
2653       url.setUrl("https://www.facebook.com/sharer.php");
2654 #ifdef HAVE_QT5
2655       QUrlQuery urlQuery;
2656       urlQuery.addQueryItem("u", linkString);
2657       urlQuery.addQueryItem("t", title);
2658       url.setQuery(urlQuery);
2659 #else
2660       url.addQueryItem("u", linkString);
2661       url.addQueryItem("t", title);
2662 #endif
2663     } else if (action->objectName() == "livejournalShareAct") {
2664       url.setUrl("http://www.livejournal.com/update.bml");
2665 #ifdef HAVE_QT5
2666       QUrlQuery urlQuery;
2667       urlQuery.addQueryItem("event", linkString);
2668       urlQuery.addQueryItem("subject", title);
2669       url.setQuery(urlQuery);
2670 #else
2671       url.addQueryItem("event", linkString);
2672       url.addQueryItem("subject", title);
2673 #endif
2674     } else if (action->objectName() == "pocketShareAct") {
2675       url.setUrl("https://getpocket.com/save");
2676 #ifdef HAVE_QT5
2677       QUrlQuery urlQuery;
2678       urlQuery.addQueryItem("url", linkString);
2679       urlQuery.addQueryItem("title", title);
2680       url.setQuery(urlQuery);
2681 #else
2682       url.addQueryItem("url", linkString);
2683       url.addQueryItem("title", title);
2684 #endif
2685     } else if (action->objectName() == "twitterShareAct") {
2686       url.setUrl("https://twitter.com/share");
2687 #ifdef HAVE_QT5
2688       QUrlQuery urlQuery;
2689       urlQuery.addQueryItem("url", linkString);
2690       urlQuery.addQueryItem("text", title);
2691       url.setQuery(urlQuery);
2692 #else
2693       url.addQueryItem("url", linkString);
2694       url.addQueryItem("text", title);
2695 #endif
2696     } else if (action->objectName() == "vkShareAct") {
2697       url.setUrl("https://vk.com/share.php");
2698 #ifdef HAVE_QT5
2699       QUrlQuery urlQuery;
2700       urlQuery.addQueryItem("url", linkString);
2701       urlQuery.addQueryItem("title", title);
2702       urlQuery.addQueryItem("description", "");
2703       urlQuery.addQueryItem("image", "");
2704       url.setQuery(urlQuery);
2705 #else
2706       url.addQueryItem("url", linkString);
2707       url.addQueryItem("title", title);
2708       url.addQueryItem("description", "");
2709       url.addQueryItem("image", "");
2710 #endif
2711     } else if (action->objectName() == "linkedinShareAct") {
2712       url.setUrl("https://www.linkedin.com/shareArticle?mini=true");
2713 #ifdef HAVE_QT5
2714       QUrlQuery urlQuery;
2715       urlQuery.addQueryItem("url", linkString);
2716       urlQuery.addQueryItem("title", title);
2717       url.setQuery(urlQuery);
2718 #else
2719       url.addQueryItem("url", linkString);
2720       url.addQueryItem("title", title);
2721 #endif
2722     } else if (action->objectName() == "bloggerShareAct") {
2723       url.setUrl("https://www.blogger.com/blog_this.pyra?t");
2724 #ifdef HAVE_QT5
2725       QUrlQuery urlQuery;
2726       urlQuery.addQueryItem("u", linkString);
2727       urlQuery.addQueryItem("n", title);
2728       url.setQuery(urlQuery);
2729 #else
2730       url.addQueryItem("u", linkString);
2731       url.addQueryItem("n", title);
2732 #endif
2733     } else if (action->objectName() == "printfriendlyShareAct") {
2734       url.setUrl("https://www.printfriendly.com/print");
2735 #ifdef HAVE_QT5
2736       QUrlQuery urlQuery;
2737       urlQuery.addQueryItem("url", linkString);
2738       url.setQuery(urlQuery);
2739 #else
2740       url.addQueryItem("url", linkString);
2741 #endif
2742     } else if (action->objectName() == "instapaperShareAct") {
2743       url.setUrl("https://www.instapaper.com/hello2");
2744 #ifdef HAVE_QT5
2745       QUrlQuery urlQuery;
2746       urlQuery.addQueryItem("url", linkString);
2747       urlQuery.addQueryItem("title", title);
2748       url.setQuery(urlQuery);
2749 #else
2750       url.addQueryItem("url", linkString);
2751       url.addQueryItem("title", title);
2752 #endif
2753     } else if (action->objectName() == "redditShareAct") {
2754       url.setUrl("https://reddit.com/submit");
2755 #ifdef HAVE_QT5
2756       QUrlQuery urlQuery;
2757       urlQuery.addQueryItem("url", linkString);
2758       urlQuery.addQueryItem("title", title);
2759       url.setQuery(urlQuery);
2760 #else
2761       url.addQueryItem("url", linkString);
2762       url.addQueryItem("title", title);
2763 #endif
2764     } else if (action->objectName() == "hackerNewsShareAct") {
2765       url.setUrl("http://news.ycombinator.com/submitlink");
2766 #ifdef HAVE_QT5
2767       QUrlQuery urlQuery;
2768       urlQuery.addQueryItem("u", linkString);
2769       urlQuery.addQueryItem("t", title);
2770       url.setQuery(urlQuery);
2771 #else
2772       url.addQueryItem("u", linkString);
2773       url.addQueryItem("t", title);
2774 #endif
2775     } else if (action->objectName() == "telegramShareAct") {
2776       url.setUrl("tg://msg_url");
2777 #ifdef HAVE_QT5
2778       QUrlQuery urlQuery;
2779       urlQuery.addQueryItem("url", linkString);
2780       urlQuery.addQueryItem("text", title);
2781       url.setQuery(urlQuery);
2782 #else
2783       url.addQueryItem("url", linkString);
2784       url.addQueryItem("text", title);
2785 #endif
2786       externalApp = true;
2787     } else if (action->objectName() == "viberShareAct") {
2788       url.setUrl("viber://forward");
2789 #ifdef HAVE_QT5
2790       QUrlQuery urlQuery;
2791       urlQuery.addQueryItem("text", title + "%20" + linkString);
2792       url.setQuery(urlQuery);
2793 #else
2794       url.addQueryItem("text", title + "%20" + linkString);
2795 #endif
2796       externalApp = true;
2797     }
2798 
2799     if ((mainWindow_->externalBrowserOn_ <= 0) && !externalApp) {
2800       mainWindow_->openNewsTab_ = NEW_TAB_FOREGROUND;
2801       mainWindow_->createWebTab(url);
2802     } else {
2803       QDesktopServices::openUrl(url);
2804     }
2805   }
2806 }
2807 //-----------------------------------------------------------------------------
getUnreadCount(QString countString)2808 int NewsTabWidget::getUnreadCount(QString countString)
2809 {
2810   if (countString.isEmpty()) return 0;
2811 
2812   countString.remove(QzRegExp("[()]"));
2813   switch (type_) {
2814   case TabTypeUnread:
2815     return countString.toInt();
2816   case TabTypeStar:
2817   case TabTypeLabel:
2818     return countString.section("/", 0, 0).toInt();
2819   default:
2820     return 0;
2821   }
2822 }
2823 
getLinkNews(int row)2824 QString NewsTabWidget::getLinkNews(int row)
2825 {
2826   QString linkString = newsModel_->dataField(row, "link_href").toString();
2827   if (linkString.isEmpty())
2828     linkString = newsModel_->dataField(row, "link_alternate").toString();
2829   return linkString.simplified();
2830 }
2831 
savePageAsDescript()2832 void NewsTabWidget::savePageAsDescript()
2833 {
2834   if (type_ >= TabTypeWeb) return;
2835 
2836   QModelIndex curIndex = newsView_->currentIndex();
2837   if (!curIndex.isValid()) return;
2838 
2839   QString html = webView_->page()->currentFrame()->toHtml().replace("'", "''");
2840   newsModel_->setData(
2841         newsModel_->index(curIndex.row(), newsModel_->fieldIndex("content")),
2842         html);
2843   int newsId = newsModel_->dataField(curIndex.row(), "id").toInt();
2844   QString qStr = QString("UPDATE news SET content='%1' WHERE id=='%2'").
2845       arg(html).arg(newsId);
2846   mainApp->sqlQueryExec(qStr);
2847 }
2848 
getHtmlLabels(int row)2849 QString NewsTabWidget::getHtmlLabels(int row)
2850 {
2851   QStringList strLabelIdList = newsModel_->dataField(row, "label").toString().
2852       split(",", QString::SkipEmptyParts);
2853   QString labelsString;
2854   QList<QTreeWidgetItem *> labelListItems = mainWindow_->categoriesTree_->getLabelListItems();
2855   foreach (QTreeWidgetItem *item, labelListItems) {
2856     if (strLabelIdList.contains(item->text(2))) {
2857       strLabelIdList.removeOne(item->text(2));
2858       QByteArray byteArray = item->data(0, CategoriesTreeWidget::ImageRole).toByteArray();
2859       labelsString.append(QString("<td><img class='quiterss-img' src=\"data:image/png;base64,") % byteArray.toBase64() % "\"/></td>");
2860       labelsString.append("<td>" % item->text(0));
2861       if (strLabelIdList.count())
2862         labelsString.append(",");
2863       labelsString.append("</td>");
2864     }
2865   }
2866   return labelsString;
2867 }
2868 
actionNewspaper(QUrl url)2869 void NewsTabWidget::actionNewspaper(QUrl url)
2870 {
2871   QString newsId = url.fragment();
2872   QModelIndex startIndex = newsModel_->index(0, newsModel_->fieldIndex("id"));
2873   QModelIndexList indexList = newsModel_->match(startIndex, Qt::EditRole, newsId);
2874   if (!indexList.isEmpty()) {
2875     QString iconStr;
2876     if (url.host() == "read.action.ui") {
2877       QString titleStyle;
2878       if (newsModel_->dataField(indexList.first().row(), "read").toInt() == 0) {
2879         slotSetItemRead(indexList.first(), 1);
2880         iconStr = "qrc:/images/bulletRead";
2881         titleStyle = "read";
2882       } else {
2883         slotSetItemRead(indexList.first(), 0);
2884         iconStr = "qrc:/images/bulletUnread";
2885         titleStyle = "unread";
2886       }
2887       QWebElement document = webView_->page()->mainFrame()->documentElement();
2888       QWebElement newsItem = document.findFirst(QString("div[id=newsItem%1]").arg(newsId));
2889       if (!newsItem.isNull()) {
2890         webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, true);
2891         QWebElement element = newsItem.findFirst(QString("img[id=readAction%1]").arg(newsId));
2892         if (!element.isNull())
2893           element.setAttribute("src", iconStr);
2894         element = newsItem.findFirst(QString("a[id=title%1]").arg(newsId));
2895         if (!element.isNull())
2896           element.setAttribute("class", titleStyle);
2897         webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages_);
2898       }
2899     } else if (url.host() == "star.action.ui") {
2900       int row = indexList.first().row();
2901       if (newsModel_->dataField(row, "starred").toInt() == 0) {
2902         slotSetItemStar(newsModel_->index(row, newsModel_->fieldIndex("starred")), 1);
2903         iconStr = "qrc:/images/starOn";
2904       } else {
2905         slotSetItemStar(newsModel_->index(row, newsModel_->fieldIndex("starred")), 0);
2906         iconStr = "qrc:/images/starOff";
2907       }
2908       QWebElement document = webView_->page()->mainFrame()->documentElement();
2909       QWebElement newsItem = document.findFirst(QString("div[id=newsItem%1]").arg(newsId));
2910       if (!newsItem.isNull()) {
2911         QWebElement element = newsItem.findFirst(QString("img[id=starAction%1]").arg(newsId));
2912         if (!element.isNull()) {
2913           webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, true);
2914           element.setAttribute("src", iconStr);
2915           webView_->settings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages_);
2916         }
2917       }
2918     } else if (url.host() == "labels.menu.ui") {
2919       newsView_->selectionModel()->clearSelection();
2920       newsView_->selectionModel()->select(
2921             indexList.first(), QItemSelectionModel::Select|QItemSelectionModel::Rows);
2922       currentNewsIdOld = newsId.toInt();
2923       mainWindow_->newsLabelMenu_->popup(QCursor::pos());
2924     } else if (url.host() == "share.menu.ui") {
2925       newsView_->selectionModel()->clearSelection();
2926       newsView_->selectionModel()->select(
2927             indexList.first(), QItemSelectionModel::Select|QItemSelectionModel::Rows);
2928       currentNewsIdOld = newsId.toInt();
2929       mainWindow_->shareMenu_->popup(QCursor::pos());
2930     } else if (url.host() == "open.browser.ui") {
2931       QUrl url = QUrl::fromEncoded(getLinkNews(indexList.first().row()).toUtf8());
2932       if (url.host().isEmpty() || (QUrl(url).host().indexOf('.') == -1)) {
2933         QString feedId = newsModel_->dataField(indexList.first().row(), "feedId").toString();
2934         QModelIndex feedIndex = feedsModel_->indexById(feedId.toInt());
2935         QUrl hostUrl = feedsModel_->dataField(feedIndex, "htmlUrl").toString();
2936 
2937         url.setScheme(hostUrl.scheme());
2938         url.setHost(hostUrl.host());
2939       }
2940       openUrl(url);
2941     } else if (url.host() == "delete.action.ui") {
2942       newsView_->selectionModel()->clearSelection();
2943       newsView_->selectionModel()->select(
2944             indexList.first(), QItemSelectionModel::Select|QItemSelectionModel::Rows);
2945       deleteNews();
2946       QWebElement document = webView_->page()->mainFrame()->documentElement();
2947       QWebElement newsItem = document.findFirst(QString("div[id=newsItem%1]").arg(newsId));
2948       if (!newsItem.isNull()) {
2949         newsItem.removeFromDocument();
2950       }
2951     }
2952   }
2953 }
2954