File indexing completed on 2024-05-19 05:01:24
0001 /* 0002 SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies) 0003 SPDX-FileCopyrightText: 2006 George Staikos <staikos@kde.org> 0004 SPDX-FileCopyrightText: 2006 Dirk Mueller <mueller@kde.org> 0005 SPDX-FileCopyrightText: 2006 Zack Rusin <zack@kde.org> 0006 SPDX-FileCopyrightText: 2006 Simon Hausmann <hausmann@kde.org> 0007 0008 SPDX-License-Identifier: BSD-2-Clause 0009 */ 0010 0011 #include <KAboutData> 0012 #include <QDebug> 0013 #include <KUriFilter> 0014 #include <KLineEdit> 0015 #include <KPluginMetaData> 0016 #include <webenginepart.h> 0017 #include <profile.h> 0018 0019 #include <QJsonDocument> 0020 #include <QInputDialog> 0021 0022 //#include <QUiLoader> 0023 //#include <QWebEnginePage> 0024 #include <QWebEngineView> 0025 //#include <QWebFrame> 0026 #include <QWebEngineSettings> 0027 //#include <QWebElement> 0028 //#include <QWebElementCollection> 0029 0030 #if !defined(QT_NO_PRINTER) 0031 #include <QPrintPreviewDialog> 0032 #endif 0033 0034 #include <QAction> 0035 #include <QCompleter> 0036 #include <QMainWindow> 0037 #include <QMenu> 0038 #include <QMenuBar> 0039 #include <QProgressBar> 0040 #include <QStatusBar> 0041 #include <QStringListModel> 0042 #include <QToolBar> 0043 #include <QToolTip> 0044 #include <QDir> 0045 #include <QFile> 0046 #include <QVector> 0047 #include <QTextStream> 0048 #include <QApplication> 0049 #include <KLocalizedString> 0050 #include <QCommandLineParser> 0051 0052 0053 class MainWindow : public QMainWindow 0054 { 0055 Q_OBJECT 0056 public: 0057 MainWindow(const QString& url = QString()): currentZoom(100) { 0058 QJsonObject jo = QJsonDocument::fromJson( 0059 "{ \"KPlugin\": {\n" 0060 " \"Id\": \"webenginepart\",\n" 0061 " \"Name\": \"WebEngine\",\n" 0062 " \"Version\": \"0.1\"\n" 0063 "}\n}").object(); 0064 KPluginMetaData metaData(jo, QString()); 0065 view = new WebEnginePart(this, nullptr, metaData); 0066 setCentralWidget(view->widget()); 0067 0068 connect(view->view(), &QWebEngineView::loadFinished, 0069 this, &MainWindow::loadFinished); 0070 connect(view->view(), SIGNAL(titleChanged(QString)), 0071 this, SLOT(setWindowTitle(QString))); 0072 connect(view->view()->page(), SIGNAL(linkHovered(QString)), 0073 this, SLOT(showLinkHover(QString))); 0074 connect(view->view()->page(), SIGNAL(windowCloseRequested()), this, SLOT(deleteLater())); 0075 0076 setupUI(); 0077 0078 QUrl qurl(KUriFilter::self()->filteredUri(url, QStringList() << QStringLiteral("kshorturifilter"))); 0079 if (qurl.isValid()) { 0080 urlEdit->setText(qurl.toEncoded()); 0081 view->openUrl(qurl); 0082 0083 // the zoom values are chosen to be like in Mozilla Firefox 3 0084 zoomLevels << 30 << 50 << 67 << 80 << 90; 0085 zoomLevels << 100; 0086 zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300; 0087 } 0088 } 0089 0090 QWebEnginePage* webPage() const { 0091 return view->view()->page(); 0092 } 0093 0094 QWebEngineView* webView() const { 0095 return view->view(); 0096 } 0097 0098 protected slots: 0099 0100 void changeLocation() { 0101 QUrl url (KUriFilter::self()->filteredUri(urlEdit->text(), QStringList() << QStringLiteral("kshorturifilter"))); 0102 view->openUrl(url); 0103 view->view()->setFocus(Qt::OtherFocusReason); 0104 } 0105 0106 void loadFinished() { 0107 urlEdit->setText(view->url().toString()); 0108 0109 QUrl::FormattingOptions opts; 0110 opts |= QUrl::RemoveScheme; 0111 opts |= QUrl::RemoveUserInfo; 0112 opts |= QUrl::StripTrailingSlash; 0113 QString s = view->url().toString(opts); 0114 s = s.mid(2); 0115 if (s.isEmpty()) 0116 return; 0117 0118 if (!urlList.contains(s)) 0119 urlList += s; 0120 urlModel.setStringList(urlList); 0121 } 0122 0123 void showLinkHover(const QString &link) { 0124 statusBar()->showMessage(link); 0125 } 0126 0127 void zoomIn() { 0128 int i = zoomLevels.indexOf(currentZoom); 0129 Q_ASSERT(i >= 0); 0130 if (i < zoomLevels.count() - 1) 0131 currentZoom = zoomLevels[i + 1]; 0132 0133 view->view()->setZoomFactor(qreal(currentZoom)/100.0); 0134 } 0135 0136 void zoomOut() { 0137 int i = zoomLevels.indexOf(currentZoom); 0138 Q_ASSERT(i >= 0); 0139 if (i > 0) 0140 currentZoom = zoomLevels[i - 1]; 0141 0142 view->view()->setZoomFactor(qreal(currentZoom)/100.0); 0143 } 0144 0145 void resetZoom() 0146 { 0147 currentZoom = 100; 0148 view->view()->setZoomFactor(1.0); 0149 } 0150 0151 void toggleZoomTextOnly(bool b) 0152 { 0153 // view->view()->page()->settings()->setAttribute(QWebEngineSettings::ZoomTextOnly, b); 0154 } 0155 0156 void print() { 0157 #if !defined(QT_NO_PRINTER) 0158 QScopedPointer<QPrintPreviewDialog> dlg (new QPrintPreviewDialog(this)); 0159 connect(dlg.data(), SIGNAL(paintRequested(QPrinter*)), 0160 view, SLOT(print(QPrinter*))); 0161 dlg->exec(); 0162 #endif 0163 } 0164 0165 void setEditable(bool on) { 0166 // view->view()->page()->setContentEditable(on); 0167 formatMenuAction->setVisible(on); 0168 } 0169 0170 void dumpHtml() { 0171 view->view()->page()->toHtml([](const QString& text) { 0172 qDebug() << "HTML: " << text; 0173 }); 0174 } 0175 0176 void selectElements() { 0177 bool ok; 0178 QString str = QInputDialog::getText(this, i18nc("input dialog window title for selecting html elements", "Select elements"), 0179 i18nc("input dialog text for selecting html elements", "Choose elements"), QLineEdit::Normal, 0180 QStringLiteral("a"), &ok); 0181 if (ok && !str.isEmpty()) { 0182 //QWebElementCollection collection = view->page()->mainFrame()->findAllElements(str); 0183 //const int count = collection.count(); 0184 //for (int i=0; i < count; i++) 0185 // collection.at(i).setStyleProperty("background-color", "yellow"); 0186 //statusBar()->showMessage(i18np("%1 element selected", "%1 elements selected", count), 5000); 0187 } 0188 } 0189 0190 public slots: 0191 0192 void newWindow(const QString &url = QString()) { 0193 MainWindow *mw = new MainWindow(url); 0194 mw->show(); 0195 } 0196 0197 private: 0198 0199 QVector<int> zoomLevels; 0200 int currentZoom; 0201 0202 // create the status bar, tool bar & menu 0203 void setupUI() { 0204 progress = new QProgressBar(this); 0205 progress->setRange(0, 100); 0206 progress->setMinimumSize(100, 20); 0207 progress->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); 0208 progress->hide(); 0209 statusBar()->addPermanentWidget(progress); 0210 0211 connect(view->view(), SIGNAL(loadProgress(int)), progress, SLOT(show())); 0212 connect(view->view(), SIGNAL(loadProgress(int)), progress, SLOT(setValue(int))); 0213 connect(view->view(), SIGNAL(loadFinished(bool)), progress, SLOT(hide())); 0214 0215 urlEdit = new KLineEdit(this); 0216 urlEdit->setSizePolicy(QSizePolicy::Expanding, urlEdit->sizePolicy().verticalPolicy()); 0217 connect(urlEdit, SIGNAL(returnPressed()), 0218 SLOT(changeLocation())); 0219 QCompleter *completer = new QCompleter(this); 0220 urlEdit->setCompleter(completer); 0221 completer->setModel(&urlModel); 0222 0223 QToolBar *bar = addToolBar(QStringLiteral("Navigation")); 0224 bar->addAction(view->view()->pageAction(QWebEnginePage::Back)); 0225 bar->addAction(view->view()->pageAction(QWebEnginePage::Forward)); 0226 bar->addAction(view->view()->pageAction(QWebEnginePage::Reload)); 0227 bar->addAction(view->view()->pageAction(QWebEnginePage::Stop)); 0228 bar->addWidget(urlEdit); 0229 0230 QMenu *fileMenu = menuBar()->addMenu(i18n("&File")); 0231 QAction *newWindow = fileMenu->addAction(i18n("New Window"), this, SLOT(newWindow())); 0232 0233 fileMenu->addAction(i18n("Print"), this, SLOT(print())); 0234 fileMenu->addAction(i18n("Close"), this, SLOT(close())); 0235 0236 QMenu *editMenu = menuBar()->addMenu(i18n("&Edit")); 0237 editMenu->addAction(view->view()->pageAction(QWebEnginePage::Undo)); 0238 editMenu->addAction(view->view()->pageAction(QWebEnginePage::Redo)); 0239 editMenu->addSeparator(); 0240 editMenu->addAction(view->view()->pageAction(QWebEnginePage::Cut)); 0241 editMenu->addAction(view->view()->pageAction(QWebEnginePage::Copy)); 0242 editMenu->addAction(view->view()->pageAction(QWebEnginePage::Paste)); 0243 editMenu->addSeparator(); 0244 QAction *setEditable = editMenu->addAction(i18n("Set Editable"), this, SLOT(setEditable(bool))); 0245 setEditable->setCheckable(true); 0246 0247 QMenu *viewMenu = menuBar()->addMenu(i18n("&View")); 0248 viewMenu->addAction(view->view()->pageAction(QWebEnginePage::Stop)); 0249 viewMenu->addAction(view->view()->pageAction(QWebEnginePage::Reload)); 0250 viewMenu->addSeparator(); 0251 QAction *zoomIn = viewMenu->addAction(i18n("Zoom &In"), this, SLOT(zoomIn())); 0252 QAction *zoomOut = viewMenu->addAction(i18n("Zoom &Out"), this, SLOT(zoomOut())); 0253 QAction *resetZoom = viewMenu->addAction(i18n("Reset Zoom"), this, SLOT(resetZoom())); 0254 QAction *zoomTextOnly = viewMenu->addAction(i18n("Zoom Text Only"), this, SLOT(toggleZoomTextOnly(bool))); 0255 zoomTextOnly->setCheckable(true); 0256 zoomTextOnly->setChecked(false); 0257 viewMenu->addSeparator(); 0258 viewMenu->addAction(i18n("Dump HTML"), this, SLOT(dumpHtml())); 0259 0260 #if 0 0261 QMenu *formatMenu = new QMenu(i18n("F&ormat")); 0262 formatMenuAction = menuBar()->addMenu(formatMenu); 0263 formatMenuAction->setVisible(false); 0264 formatMenu->addAction(view->view()->pageAction(QWebEnginePage::ToggleBold)); 0265 formatMenu->addAction(view->view()->pageAction(QWebEnginePage::ToggleItalic)); 0266 formatMenu->addAction(view->view()->pageAction(QWebEnginePage::ToggleUnderline)); 0267 QMenu *writingMenu = formatMenu->addMenu(i18n("Writing Direction")); 0268 writingMenu->addAction(view->view()->pageAction(QWebEnginePage::SetTextDirectionDefault)); 0269 writingMenu->addAction(view->view()->pageAction(QWebEnginePage::SetTextDirectionLeftToRight)); 0270 writingMenu->addAction(view->view()->pageAction(QWebEnginePage::SetTextDirectionRightToLeft)); 0271 #endif 0272 newWindow->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_N)); 0273 view->view()->pageAction(QWebEnginePage::Back)->setShortcut(QKeySequence::Back); 0274 view->view()->pageAction(QWebEnginePage::Stop)->setShortcut(Qt::Key_Escape); 0275 view->view()->pageAction(QWebEnginePage::Forward)->setShortcut(QKeySequence::Forward); 0276 view->view()->pageAction(QWebEnginePage::Reload)->setShortcut(QKeySequence::Refresh); 0277 view->view()->pageAction(QWebEnginePage::Undo)->setShortcut(QKeySequence::Undo); 0278 view->view()->pageAction(QWebEnginePage::Redo)->setShortcut(QKeySequence::Redo); 0279 view->view()->pageAction(QWebEnginePage::Cut)->setShortcut(QKeySequence::Cut); 0280 view->view()->pageAction(QWebEnginePage::Copy)->setShortcut(QKeySequence::Copy); 0281 view->view()->pageAction(QWebEnginePage::Paste)->setShortcut(QKeySequence::Paste); 0282 zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); 0283 zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); 0284 resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); 0285 // view->view()->pageAction(QWebEnginePage::ToggleBold)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_B)); 0286 // view->view()->pageAction(QWebEnginePage::ToggleItalic)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I)); 0287 // view->view()->pageAction(QWebEnginePage::ToggleUnderline)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_U)); 0288 0289 QMenu *toolsMenu = menuBar()->addMenu(i18n("&Tools")); 0290 toolsMenu->addAction(i18n("Select elements..."), this, SLOT(selectElements())); 0291 0292 } 0293 0294 WebEnginePart *view; 0295 KLineEdit *urlEdit; 0296 QProgressBar *progress; 0297 0298 QAction *formatMenuAction; 0299 0300 QStringList urlList; 0301 QStringListModel urlModel; 0302 }; 0303 0304 class URLLoader : public QObject 0305 { 0306 Q_OBJECT 0307 public: 0308 URLLoader(QWebEngineView* view, const QString& inputFileName) 0309 : m_view(view) 0310 , m_stdOut(stdout) 0311 { 0312 init(inputFileName); 0313 } 0314 0315 public slots: 0316 void loadNext() 0317 { 0318 QString qstr; 0319 if (getUrl(qstr)) { 0320 QUrl url(qstr, QUrl::StrictMode); 0321 if (url.isValid()) { 0322 m_stdOut << "Loading " << qstr << " ......" << Qt::endl; 0323 m_view->load(url); 0324 } else 0325 loadNext(); 0326 } else 0327 disconnect(m_view, nullptr, this, nullptr); 0328 } 0329 0330 private: 0331 void init(const QString& inputFileName) 0332 { 0333 QFile inputFile(inputFileName); 0334 if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) { 0335 QTextStream stream(&inputFile); 0336 QString line; 0337 while (true) { 0338 line = stream.readLine(); 0339 if (line.isNull()) 0340 break; 0341 m_urls.append(line); 0342 } 0343 } else { 0344 qDebug() << "Can't open list file"; 0345 exit(0); 0346 } 0347 m_index = 0; 0348 inputFile.close(); 0349 } 0350 0351 bool getUrl(QString& qstr) 0352 { 0353 if (m_index == m_urls.size()) 0354 return false; 0355 0356 qstr = m_urls[m_index++]; 0357 return true; 0358 } 0359 0360 private: 0361 QVector<QString> m_urls; 0362 int m_index; 0363 QWebEngineView* m_view; 0364 QTextStream m_stdOut; 0365 }; 0366 0367 0368 int main(int argc, char **argv) 0369 { 0370 KAboutData about(QStringLiteral("KDELauncher"), i18n("KDELauncher"), QStringLiteral("0.0000013")); 0371 QApplication app(argc, argv); 0372 QCommandLineParser parser; 0373 KAboutData::setApplicationData(about); 0374 about.setupCommandLine(&parser); 0375 parser.process(app); 0376 about.processCommandLine(&parser); 0377 0378 QString url = QStringLiteral("%1/%2").arg(QDir::homePath()).arg(QStringLiteral("index.html")); 0379 0380 const QStringList args = app.arguments(); 0381 0382 if (args.contains(QStringLiteral("-r"))) { 0383 // robotized 0384 QString listFile = args.at(2); 0385 if (!(args.count() == 3) && QFile::exists(listFile)) { 0386 qDebug() << "Usage: KDELauncher -r listfile"; 0387 exit(0); 0388 } 0389 MainWindow window; 0390 QWebEngineView *view = window.webView(); 0391 URLLoader loader(view, listFile); 0392 QObject::connect(view, SIGNAL(loadFinished(bool)), &loader, SLOT(loadNext())); 0393 loader.loadNext(); 0394 window.show(); 0395 return app.exec(); 0396 } else { 0397 if (args.count() > 1) 0398 url = args.at(1); 0399 0400 MainWindow window(url); 0401 0402 // Opens every given urls in new windows 0403 for (int i = 2; i < args.count(); i++) 0404 window.newWindow(args.at(i)); 0405 0406 window.show(); 0407 return app.exec(); 0408 } 0409 } 0410 0411 #include "webenginepart_tester.moc"