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