File indexing completed on 2024-05-05 17:19:02
0001 /*************************************************************************** 0002 * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr 0003 * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 ***************************************************************************/ 0006 /** @file 0007 * This file defines classes skgmainpanel. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgmainpanel.h" 0012 0013 #include <kaboutdata.h> 0014 #include <kactioncollection.h> 0015 #include <kactionmenu.h> 0016 #include <kcombobox.h> 0017 #include <kconfigdialog.h> 0018 #include <kencodingfiledialog.h> 0019 #include <kformat.h> 0020 #include <kmessagebox.h> 0021 #include <kmessagewidget.h> 0022 #include <knotification.h> 0023 #include <knotifyconfigwidget.h> 0024 #include <kselectaction.h> 0025 #include <kservice.h> 0026 #include <kservicetypetrader.h> 0027 #include <kstandardaction.h> 0028 #include <kstatusnotifieritem.h> 0029 #include <kstringhandler.h> 0030 #include <ktoggleaction.h> 0031 #include <ktoolbar.h> 0032 #include <ktoolbarpopupaction.h> 0033 #include <kxmlguifactory.h> 0034 #include <qvariant.h> 0035 0036 #ifdef KActivities_FOUND 0037 #include <kactivities/resourceinstance.h> 0038 #endif 0039 0040 #ifdef SKG_DBUS 0041 #include <QDBusConnection> 0042 #include <QDBusMessage> 0043 #endif 0044 0045 #include <qaction.h> 0046 #include <qapplication.h> 0047 #include <qcollator.h> 0048 #include <qcompleter.h> 0049 #include <qdesktopservices.h> 0050 #include <qdir.h> 0051 #include <qdom.h> 0052 #include <qevent.h> 0053 #include <qfiledialog.h> 0054 #include <qheaderview.h> 0055 #include <qlineedit.h> 0056 #include <qmenu.h> 0057 #include <qprocess.h> 0058 #include <qprogressbar.h> 0059 #include <qpushbutton.h> 0060 #include <qscrollarea.h> 0061 #include <qsplashscreen.h> 0062 #include <qtabbar.h> 0063 #include <qtabwidget.h> 0064 #include <qtextcodec.h> 0065 #include <qurlquery.h> 0066 #include <QRandomGenerator> 0067 0068 #include <algorithm> // std::sort 0069 0070 #include "skgdefine.h" 0071 #include "skginterfaceplugin.h" 0072 #include "skgservices.h" 0073 #include "skgtraces.h" 0074 #include "skgtransactionmng.h" 0075 #include "skgtreeview.h" 0076 #include "skgwebview.h" 0077 #include "skgzoomselector.h" 0078 0079 struct doublePointer { 0080 void* p1; 0081 void* p2; 0082 }; 0083 0084 struct historyPage { 0085 SKGTabPage::SKGPageHistoryItem current; 0086 SKGTabPage::SKGPageHistoryItemList next; 0087 SKGTabPage::SKGPageHistoryItemList previous; 0088 }; 0089 0090 struct actionDetails { 0091 QPointer<QAction> action; 0092 QStringList tables; 0093 int min{}; 0094 int max{}; 0095 int ranking{}; 0096 bool focus{}; 0097 }; 0098 class SKGMainPanelPrivate 0099 { 0100 public: 0101 Ui::skgmainpanel_base ui{}; 0102 Ui::skgmainpanel_pref uipref{}; 0103 0104 SKGTabWidget* m_tabWidget; 0105 QSplashScreen* m_splashScreen; 0106 0107 SKGDocument* m_currentDocument; 0108 0109 QList<SKGInterfacePlugin*> m_pluginsList; 0110 QMap<QString, actionDetails > m_registeredGlogalAction; 0111 QList<historyPage> m_historyClosedPages; 0112 0113 QMenu* m_contextMenu; 0114 QAction* m_actHideContextItem; 0115 QAction* m_actShowAllContextItems; 0116 QAction* m_actDelete; 0117 QAction* m_closePageAction; 0118 QAction* m_closeAllOtherPagesAction; 0119 QAction* m_switchPinState; 0120 QAction* m_saveDefaultStateAction; 0121 QAction* m_resetDefaultStateAction; 0122 QAction* m_overwriteBookmarkStateAction; 0123 QAction* m_configureAction; 0124 QAction* m_enableEditorAction; 0125 QAction* m_fullScreenAction; 0126 QAction* m_actLock; 0127 QAction* m_actUnLock; 0128 QAction* m_reopenLastClosed; 0129 KStatusNotifierItem* m_kSystemTrayIcon; 0130 QLabel* m_kNormalMessage; 0131 SKGZoomSelector* m_zoomSelector; 0132 0133 KToolBarPopupAction* m_previousAction; 0134 KToolBarPopupAction* m_nextAction; 0135 KToolBarPopupAction* m_buttonMenuAction; 0136 KToggleAction* m_showMenuBarAction; 0137 0138 QMenu* m_previousMenu; 0139 QMenu* m_nextMenu; 0140 QMenu* m_buttonMenu; 0141 QWidget* m_mainWidget; 0142 QVBoxLayout* m_mainLayout{}; 0143 0144 doublePointer m_progressObjects{}; 0145 bool m_middleClick; 0146 bool m_saveOnClose; 0147 QString m_fileName; 0148 SKGWidget* m_widgetHavingSelection; 0149 QStringList m_tipsOfTheDay; 0150 0151 #ifdef KActivities_FOUND 0152 KActivities::ResourceInstance* m_activityResourceInstance; 0153 #endif 0154 0155 static bool m_currentActionCanceled; 0156 static SKGMainPanel* m_mainPanel; 0157 0158 SKGMainPanelPrivate() 0159 { 0160 m_actHideContextItem = nullptr; m_actShowAllContextItems = nullptr; m_actDelete = nullptr; 0161 m_closePageAction = nullptr; m_closeAllOtherPagesAction = nullptr; m_switchPinState = nullptr; m_saveDefaultStateAction = nullptr; 0162 m_resetDefaultStateAction = nullptr; m_overwriteBookmarkStateAction = nullptr; m_configureAction = nullptr; m_enableEditorAction = nullptr; m_fullScreenAction = nullptr; m_actLock = nullptr; 0163 m_actUnLock = nullptr; 0164 m_kSystemTrayIcon = nullptr; 0165 m_kNormalMessage = nullptr; m_zoomSelector = nullptr; m_previousAction = nullptr; m_nextAction = nullptr; m_buttonMenuAction = nullptr; 0166 m_mainWidget = nullptr; m_mainLayout = nullptr; m_middleClick = false; m_saveOnClose = false; 0167 m_widgetHavingSelection = nullptr; 0168 m_tabWidget = nullptr; m_splashScreen = nullptr; m_currentDocument = nullptr; 0169 m_contextMenu = nullptr; 0170 m_reopenLastClosed = nullptr; 0171 m_showMenuBarAction = nullptr; 0172 m_previousMenu = nullptr; 0173 m_nextMenu = nullptr; 0174 m_buttonMenu = nullptr; 0175 m_progressObjects.p1 = nullptr; 0176 m_progressObjects.p2 = nullptr; 0177 #ifdef KActivities_FOUND 0178 m_activityResourceInstance = nullptr; 0179 #endif 0180 } 0181 0182 static int progressBarCallBack(int iPos, qint64 iTime, const QString& iName, void* iProgressBar) 0183 { 0184 Q_UNUSED(iTime) 0185 QProgressBar* progressBar = nullptr; 0186 QPushButton* button = nullptr; 0187 auto* pointers = static_cast<doublePointer*>(iProgressBar); 0188 if (pointers != nullptr) { 0189 progressBar = static_cast<QProgressBar*>(pointers->p1); 0190 button = static_cast<QPushButton*>(pointers->p2); 0191 } 0192 0193 bool visible = (iPos > 0 && iPos <= 100); 0194 if (progressBar != nullptr) { 0195 QString commonFormat = QStringLiteral("%p%"); 0196 /*if (iPos > 0) { 0197 * qint64 estimatedTime = 100 * iTime / iPos; 0198 * qint64 remainingTime = estimatedTime - iTime; 0199 * commonFormat = commonFormat % " - " % i18nc("To print a remaining time (in seconde) / estimated time (in second)", "%1s / %2s", 0200 * SKGServices::intToString(remainingTime / 1000), 0201 * SKGServices::intToString(estimatedTime / 1000)); 0202 }*/ 0203 progressBar->setFormat(iName.isEmpty() ? commonFormat : commonFormat % '\n' % iName); 0204 progressBar->setValue(iPos); 0205 progressBar->setVisible(visible); 0206 if (iPos == 100) { 0207 QTimer::singleShot(300, Qt::CoarseTimer, progressBar, &QProgressBar::hide); 0208 } 0209 progressBar->setToolTip(iName); 0210 #ifdef SKG_DBUS 0211 QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/org/") + KAboutData::applicationData().componentName() + QLatin1String("/UnityLauncher"), 0212 QStringLiteral("com.canonical.Unity.LauncherEntry"), 0213 QStringLiteral("Update")); 0214 message << "application://org.kde.skrooge.desktop"; 0215 0216 QVariantMap setProperty; 0217 if (iPos == 100) { 0218 setProperty.insert(QStringLiteral("progress"), 0.0); 0219 setProperty.insert(QStringLiteral("progress-visible"), false); 0220 } else { 0221 setProperty.insert(QStringLiteral("progress"), static_cast<double>(iPos / 100.0)); 0222 setProperty.insert(QStringLiteral("progress-visible"), true); 0223 } 0224 message << setProperty; 0225 QDBusConnection::sessionBus().send(message); 0226 #endif 0227 } 0228 if (button != nullptr) { 0229 button->setVisible(visible); 0230 if (iPos == 100) { 0231 QTimer::singleShot(300, Qt::CoarseTimer, button, &QPushButton::hide); 0232 } 0233 } 0234 0235 0236 SKGMainPanelPrivate::m_currentActionCanceled = false; 0237 if (iPos != 0 && iPos != 100) { 0238 qApp->processEvents(QEventLoop::AllEvents, 500); 0239 } 0240 return (SKGMainPanelPrivate::m_currentActionCanceled ? 1 : 0); 0241 } 0242 0243 static bool adviceLessThan(const SKGAdvice& s1, const SKGAdvice& s2) 0244 { 0245 if (s1.getPriority() == s2.getPriority()) { 0246 return (s1.getShortMessage() > s2.getShortMessage()); 0247 } 0248 return (s1.getPriority() > s2.getPriority()); 0249 } 0250 0251 static void setAttribute(QDomElement& iRoot, const QString& iPath, const QString& iValue) 0252 { 0253 int pos = iPath.indexOf('.'); 0254 if (pos == -1) { 0255 iRoot.setAttribute(iPath, iValue); 0256 } else { 0257 QString newElementName = iPath.left(pos); 0258 QString newAttribue = iPath.right(iPath.count() - pos - 1); 0259 0260 QDomDocument doc(QStringLiteral("SKGML")); 0261 doc.setContent(iRoot.attribute(newElementName)); 0262 QDomElement root = doc.documentElement(); 0263 if (root.isNull()) { 0264 root = doc.createElement(QStringLiteral("parameters")); 0265 doc.appendChild(root); 0266 } 0267 setAttribute(root, newAttribue, iValue); 0268 0269 iRoot.setAttribute(newElementName, doc.toString()); 0270 } 0271 } 0272 0273 void refreshTabPosition() 0274 { 0275 m_tabWidget->setTabPosition(static_cast<QTabWidget::TabPosition>(skgbasegui_settings::main_tabs_position())); 0276 } 0277 0278 void rebuildSystemTray() 0279 { 0280 if (skgbasegui_settings::icon_in_system_tray()) { 0281 if (m_kSystemTrayIcon == nullptr) { 0282 m_kSystemTrayIcon = new KStatusNotifierItem(m_mainPanel); 0283 m_kSystemTrayIcon->setStandardActionsEnabled(true); 0284 m_kSystemTrayIcon->setAssociatedWidget(m_mainPanel); 0285 m_kSystemTrayIcon->setIconByPixmap(QApplication::windowIcon()); 0286 } 0287 } else { 0288 if (m_kSystemTrayIcon != nullptr) { 0289 delete m_kSystemTrayIcon; 0290 m_kSystemTrayIcon = nullptr; 0291 } 0292 } 0293 } 0294 }; 0295 0296 0297 bool SKGMainPanelPrivate::m_currentActionCanceled = false; 0298 SKGMainPanel* SKGMainPanelPrivate::m_mainPanel = nullptr; 0299 0300 SKGMainPanel::SKGMainPanel(QSplashScreen* iSplashScreen, SKGDocument* iDocument) 0301 : d(new SKGMainPanelPrivate) 0302 { 0303 SKGTRACEINFUNC(1) 0304 d->m_tabWidget = new SKGTabWidget(this); 0305 d->m_splashScreen = iSplashScreen; 0306 d->m_currentDocument = iDocument; 0307 0308 setComponentName(QStringLiteral("skg"), KAboutData::applicationData().displayName()); 0309 setObjectName(qApp->applicationDisplayName()); 0310 0311 // Set main panel 0312 SKGMainPanelPrivate::m_mainPanel = this; 0313 auto w = new QScrollArea(this); 0314 w->setFrameShape(QFrame::NoFrame); 0315 w->setFocusPolicy(Qt::NoFocus); 0316 d->m_mainLayout = new QVBoxLayout(w); 0317 d->m_mainLayout->setSpacing(0); 0318 d->m_mainLayout->setContentsMargins(0, 0, 0, 0); 0319 d->m_mainLayout->addWidget(d->m_tabWidget); 0320 d->ui.setupUi(this); 0321 0322 // setMainWidget(new QLabel("hello")); 0323 0324 // Initialize settings 0325 KSharedConfigPtr config = KSharedConfig::openConfig(); 0326 KConfigGroup prefskg = config->group("Main Panel"); 0327 int option = prefskg.readEntry("update_modified_contexts", 100); 0328 if (option == 100) { 0329 // First call, we set default values 0330 prefskg.writeEntry("update_modified_contexts", 2, KConfigBase::Normal); 0331 // NEVER: set following setting 0332 #ifdef SKG_KF_5102 0333 KMessageBox::saveDontShowAgainTwoActions(QStringLiteral("updateContextOnClose"), KMessageBox::No); 0334 #else 0335 KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateContextOnClose"), KMessageBox::No); 0336 #endif 0337 SKGTRACEL(1) << "update_modified_contexts set to NEVER" << SKGENDL; 0338 SKGTRACEL(1) << "updateContextOnClose set to No" << SKGENDL; 0339 } 0340 0341 option = prefskg.readEntry("update_modified_bookmarks", 100); 0342 if (option == 100) { 0343 // First call, we set default values 0344 prefskg.writeEntry("update_modified_bookmarks", 2, KConfigBase::Normal); 0345 // NEVER: set following setting 0346 #ifdef SKG_KF_5102 0347 KMessageBox::saveDontShowAgainTwoActions(QStringLiteral("updateBookmarkOnClose"), KMessageBox::No); 0348 #else 0349 KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateBookmarkOnClose"), KMessageBox::No); 0350 #endif 0351 SKGTRACEL(1) << "update_modified_bookmarks set to NEVER" << SKGENDL; 0352 SKGTRACEL(1) << "updateBookmarkOnClose set to No" << SKGENDL; 0353 } 0354 0355 0356 const auto plugins = KPluginMetaData::findPlugins(QStringLiteral("skg_gui")); 0357 0358 // Load plugins 0359 int nb = plugins.count(); 0360 SKGTRACEL(1) << nb << " plugins found" << SKGENDL; 0361 if (d->m_splashScreen != nullptr) { 0362 d->m_splashScreen->showMessage(i18nc("Splash screen message", "Loading plugins…"), Qt::AlignLeft, QColor(221, 130, 8)); // krazy:exclude=qmethods 0363 } 0364 SKGError err; 0365 QStringList listAuthors; 0366 QStringList listTasks; 0367 QStringList listEmails; 0368 QStringList listOscs; 0369 for (int i = 0; i < nb; ++i) { 0370 const auto plugin = plugins.at(i); 0371 const auto name = plugin.name(); 0372 const auto filename = plugin.fileName(); 0373 QString id = plugin.value(QStringLiteral("X-Krunner-ID")); 0374 QString msg = i18nc("Splash screen message", "Loading plugin %1/%2: %3…", i + 1, nb, name); 0375 SKGTRACEL(1) << msg << " from " << filename << SKGENDL; 0376 if (d->m_splashScreen != nullptr) { 0377 d->m_splashScreen->showMessage(msg, Qt::AlignLeft, QColor(221, 130, 8)); // krazy:exclude=qmethods 0378 } 0379 0380 const auto factory = KPluginFactory::loadFactory(plugin); 0381 const auto pluginInterface = factory.plugin ? factory.plugin->create<SKGInterfacePlugin>(this) : nullptr; 0382 if (pluginInterface != nullptr) { 0383 if (pluginInterface->isEnabled() && pluginInterface->setupActions(getDocument())) { 0384 // Add plugin in about 0385 QStringList listOfAuthors; 0386 QStringList listOfEmails; 0387 QStringList listOfPlugins; 0388 QString author = plugin.authors().at(0).name(); 0389 QString email = plugin.authors().at(0).emailAddress(); 0390 if (!author.isEmpty()) { 0391 listOfAuthors.push_back(author); 0392 listOfEmails.push_back(email); 0393 listOfPlugins.push_back(name); 0394 } 0395 0396 const auto subPlugins = pluginInterface->subPlugins(); 0397 auto subPluginsNotFound = subPlugins; 0398 for (const QString& subPlugin : subPlugins) { 0399 const auto subOffers = KPluginMetaData::findPlugins(subPlugin); 0400 int nbSubOffers = subOffers.count(); 0401 for (int j = 0; j < nbSubOffers; ++j) { 0402 const auto subService = subOffers.at(j); 0403 subPluginsNotFound.removeAll(subPlugin); 0404 QString author2 = subService.authors().at(0).name(); 0405 QString email2 = subService.authors().at(0).emailAddress(); 0406 if (!author2.isEmpty()) { 0407 listOfAuthors.push_back(author2); 0408 listOfEmails.push_back(email2); 0409 listOfPlugins.push_back(subService.name()); 0410 } 0411 } 0412 } 0413 0414 for (const QString& subPlugin : subPluginsNotFound) { 0415 KService::List subOffers = KServiceTypeTrader::self()->query(subPlugin); 0416 int nbSubOffers = subOffers.count(); 0417 for (int j = 0; j < nbSubOffers; ++j) { 0418 KService::Ptr subService = subOffers.at(j); 0419 #ifdef SKG_KF_5102 0420 QString author2 = subService->property(QStringLiteral("X-KDE-PluginInfo-Author"), QMetaType::QString).toString(); 0421 QString email2 = subService->property(QStringLiteral("X-KDE-PluginInfo-Email"), QMetaType::QString).toString(); 0422 #else 0423 QString author2 = subService->property(QStringLiteral("X-KDE-PluginInfo-Author"), QVariant::String).toString(); 0424 QString email2 = subService->property(QStringLiteral("X-KDE-PluginInfo-Email"), QVariant::String).toString(); 0425 #endif 0426 if (!author2.isEmpty()) { 0427 listOfAuthors.push_back(author2); 0428 listOfEmails.push_back(email2); 0429 listOfPlugins.push_back(subService->name()); 0430 } 0431 } 0432 } 0433 0434 int nbAuthors = listOfAuthors.count(); 0435 for (int j = 0; j < nbAuthors; ++j) { 0436 QString authorId; 0437 QString author = listOfAuthors.at(j); 0438 QStringList authors = SKGServices::splitCSVLine(author, ','); 0439 if (authors.count() == 2) { 0440 author = authors.at(0); 0441 authorId = authors.at(1); 0442 } 0443 int pos2 = listAuthors.indexOf(author); 0444 if (pos2 == -1) { 0445 listAuthors.push_back(author); 0446 listTasks.push_back(i18n("Developer of plugin '%1'", listOfPlugins.at(j))); 0447 listEmails.push_back(listOfEmails.at(j)); 0448 listOscs.push_back(authorId); 0449 } else { 0450 listTasks[pos2] += i18n(", '%1'", listOfPlugins.at(j)); 0451 } 0452 } 0453 0454 // Store plugin 0455 int nbplugin = d->m_pluginsList.count(); 0456 int pos3 = nbplugin; 0457 for (int j = nbplugin - 1; j >= 0; --j) { 0458 if (pluginInterface->getOrder() < d->m_pluginsList.at(j)->getOrder()) { 0459 pos3 = j; 0460 } 0461 } 0462 0463 d->m_pluginsList.insert(pos3, pluginInterface); 0464 pluginInterface->setObjectName(id); 0465 0466 // Add tips 0467 d->m_tipsOfTheDay += pluginInterface->tips(); 0468 } else { 0469 SKGTRACEL(1) << "Disabled" << SKGENDL; 0470 } 0471 } else { 0472 SKGTRACEL(1) << "Loading error: " << factory.errorString << SKGENDL; 0473 } 0474 } 0475 0476 // Add credits 0477 KAboutData about = KAboutData::applicationData(); 0478 nb = listAuthors.count(); 0479 for (int i = 0; i < nb; ++i) { 0480 about.addCredit(listAuthors.at(i), listTasks.at(i), listEmails.at(i), QLatin1String(""), listOscs.at(i)); 0481 } 0482 KAboutData::setApplicationData(about); 0483 0484 // accept dnd 0485 setAcceptDrops(true); 0486 0487 // tell the KXmlGuiWindow that this is indeed the main widget 0488 setCentralWidget(w); 0489 0490 d->refreshTabPosition(); 0491 d->m_tabWidget->setMovable(true); 0492 d->m_tabWidget->setTabsClosable(true); 0493 d->m_tabWidget->setUsesScrollButtons(true); 0494 d->m_tabWidget->tabBar()->setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); 0495 d->m_tabWidget->setDocumentMode(true); 0496 d->m_tabWidget->show(); 0497 0498 // System tray 0499 d->rebuildSystemTray(); 0500 0501 // then, setup our actions 0502 setupActions(); 0503 0504 displayErrorMessage(err); 0505 0506 // Add a status bar 0507 statusBar()->show(); 0508 0509 QPalette palette2 = QApplication::palette(); 0510 palette2.setColor(QPalette::Base, Qt::transparent); 0511 d->ui.kContextList->setPalette(palette2); 0512 0513 QAction* toggle = d->ui.kDockContext->toggleViewAction(); 0514 QAction* panelAction = actionCollection()->addAction(QStringLiteral("view_context")); 0515 registerGlobalAction(QStringLiteral("view_context"), panelAction); 0516 panelAction->setCheckable(true); 0517 panelAction->setChecked(toggle->isChecked()); 0518 panelAction->setText(toggle->text()); 0519 actionCollection()->setDefaultShortcut(panelAction, Qt::SHIFT + Qt::Key_F9); 0520 connect(panelAction, &QAction::triggered, toggle, &QAction::trigger); 0521 connect(toggle, &QAction::toggled, panelAction, &QAction::setChecked); 0522 0523 QAction* toggle2 = d->ui.kDockMessages->toggleViewAction(); 0524 QAction* panelAction2 = actionCollection()->addAction(QStringLiteral("view_messages")); 0525 registerGlobalAction(QStringLiteral("view_messages"), panelAction2); 0526 panelAction2->setCheckable(true); 0527 panelAction2->setChecked(toggle2->isChecked()); 0528 panelAction2->setText(toggle2->text()); 0529 actionCollection()->setDefaultShortcut(panelAction2, Qt::SHIFT + Qt::Key_F8); 0530 connect(panelAction2, &QAction::triggered, toggle2, &QAction::trigger); 0531 connect(toggle2, &QAction::toggled, panelAction2, &QAction::setChecked); 0532 0533 auto contextMenu = new KSelectAction(SKGServices::fromTheme(QStringLiteral("tab-new")), i18nc("Noun", "Pages"), this); 0534 registerGlobalAction(QStringLiteral("view_contextmenu"), contextMenu); 0535 0536 // Add plugin in client in right order 0537 QList<QListWidgetItem*> pageNotVisible; 0538 KConfigGroup prefContextVisibility = config->group("Context Visibility"); 0539 int shortCutIndex = 0; 0540 QString shortCutPrefix = QStringLiteral("Ctrl+"); 0541 int nbplugin = d->m_pluginsList.count(); 0542 QList<QAction*> contextActionList; 0543 for (int j = 0; j < nbplugin; ++j) { 0544 SKGInterfacePlugin* pluginInterface = d->m_pluginsList.at(j); 0545 if (pluginInterface != nullptr) { 0546 // Creation of the item 0547 QString title = pluginInterface->title(); 0548 SKGTRACEL(1) << "Add plugin (" << pluginInterface->getOrder() << ") : " << title << SKGENDL; 0549 if (!title.isEmpty()) { 0550 // Add menu item with shortcuts 0551 if (pluginInterface->isInPagesChooser()) { 0552 bool visible = prefContextVisibility.readEntry(pluginInterface->objectName(), true); 0553 QIcon icon = SKGServices::fromTheme(pluginInterface->icon()); 0554 0555 auto contextItem = new QListWidgetItem(icon, title); 0556 contextItem->setStatusTip(pluginInterface->statusTip()); 0557 contextItem->setToolTip(pluginInterface->toolTip()); 0558 contextItem->setData(12, j); // context item ==> plugin 0559 int page2 = d->ui.kContextList->count(); 0560 pluginInterface->setProperty("contextItem", page2); // plugin ==> context item 0561 0562 d->ui.kContextList->addItem(contextItem); 0563 0564 QAction* newAction = contextMenu->addAction(icon, title); 0565 if (newAction != nullptr) { 0566 newAction->setCheckable(false); 0567 newAction->setData(page2); 0568 contextItem->setData(15, QVariant::fromValue(static_cast<void*>(newAction))); // context item ==> action 0569 if (!shortCutPrefix.isEmpty()) { 0570 ++shortCutIndex; 0571 if (shortCutIndex == 10) { 0572 shortCutIndex = 0; 0573 if (shortCutPrefix == QStringLiteral("Ctrl+")) { 0574 shortCutPrefix += QStringLiteral("Alt+"); 0575 } else { 0576 shortCutPrefix = QLatin1String(""); 0577 } 0578 } 0579 if (!shortCutPrefix.isEmpty()) { 0580 actionCollection()->setDefaultShortcut(newAction, QString(shortCutPrefix % SKGServices::intToString(shortCutIndex))); 0581 } 0582 } 0583 connect(newAction, &QAction::triggered, this, &SKGMainPanel::onOpenContext); 0584 0585 contextActionList.append(newAction); 0586 0587 if (!visible) { 0588 pageNotVisible.push_back(contextItem); 0589 } 0590 0591 // Register action 0592 QString id = "page_" % pluginInterface->objectName(); 0593 registerGlobalAction(id, newAction); 0594 registerGlobalAction(id, newAction); 0595 } 0596 } 0597 0598 // Create dock if needed 0599 QDockWidget* dockWidget = pluginInterface->getDockWidget(); 0600 if (dockWidget != nullptr) { 0601 addDockWidget(Qt::LeftDockWidgetArea, dockWidget); 0602 tabifyDockWidget(d->ui.kDockContext, dockWidget); 0603 tabifyDockWidget(dockWidget, d->ui.kDockContext); 0604 } 0605 } 0606 } 0607 } 0608 0609 // Lock docs if needed 0610 KConfigGroup pref = getMainConfigGroup(); 0611 if (pref.readEntry("docks_locked", false)) { 0612 onLockDocks(); 0613 } 0614 0615 if (!pref.readEntry("first_launch", false)) { 0616 this->setWindowState(windowState() | Qt::WindowMaximized); 0617 pref.writeEntry("first_launch", true); 0618 } 0619 0620 // a call to KXmlGuiWindow::setupGUI() populates the GUI 0621 // with actions, using KXMLGUI. 0622 // It also applies the saved mainwindow settings, if any, and ask the 0623 // mainwindow to automatically save settings if changed: window size, 0624 // toolbar position, icon size, etc. 0625 setupGUI(Default, QStringLiteral("skgmainpanel.rc")); 0626 plugActionList(QStringLiteral("context_actionlist"), contextActionList); 0627 0628 for (int j = 0; j < nbplugin; ++j) { 0629 SKGInterfacePlugin* pluginInterface = d->m_pluginsList.at(j); 0630 if (pluginInterface != nullptr) { 0631 QString title = pluginInterface->title(); 0632 SKGTRACEL(1) << "Add plugin client (" << pluginInterface->getOrder() << ") : " << title << SKGENDL; 0633 guiFactory()->addClient(pluginInterface); 0634 } 0635 } 0636 0637 // Hide items in context 0638 nb = pageNotVisible.count(); 0639 for (int i = 0; i < nb; ++i) { 0640 setContextVisibility(pageNotVisible.at(i), false); 0641 } 0642 0643 // Set status bar 0644 d->m_kNormalMessage = new QLabel(this); 0645 d->m_kNormalMessage->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred)); 0646 0647 auto kProgressBar = new QProgressBar(this); 0648 kProgressBar->setObjectName(QStringLiteral("kProgressBar")); 0649 kProgressBar->setValue(0); 0650 kProgressBar->setMinimumSize(100, 20); 0651 QSizePolicy sizePolicyProgessBar(QSizePolicy::Fixed, QSizePolicy::Expanding); 0652 kProgressBar->setSizePolicy(sizePolicyProgessBar); 0653 kProgressBar->setToolTip(i18nc("Widget description", "Progress of the current action")); 0654 QFont f = kProgressBar->font(); 0655 f.setPointSize(6.0); 0656 kProgressBar->setFont(f); 0657 kProgressBar->setVisible(false); 0658 kProgressBar->setAlignment(Qt::AlignTop | Qt::AlignHCenter); 0659 kProgressBar->setRange(0, 100); 0660 0661 d->m_zoomSelector = new SKGZoomSelector(this); 0662 d->m_zoomSelector->setSizePolicy(sizePolicyProgessBar); 0663 connect(d->m_zoomSelector, &SKGZoomSelector::changed, this, &SKGMainPanel::onZoomChanged); 0664 0665 statusBar()->addWidget(d->m_kNormalMessage, 1); 0666 statusBar()->addPermanentWidget(kProgressBar); 0667 0668 // Set Cancel button 0669 auto kCancelButton = new QPushButton(); 0670 kCancelButton->setObjectName(QStringLiteral("kCancelButton")); 0671 kCancelButton->setIcon(SKGServices::fromTheme(QStringLiteral("media-playback-stop"))); 0672 kCancelButton->setToolTip(i18nc("Widget description", "Cancel the current action")); 0673 kCancelButton->setStatusTip(i18nc("Widget description", "Cancel the current action")); 0674 kCancelButton->setVisible(false); 0675 connect(kCancelButton, &QPushButton::clicked, this, &SKGMainPanel::onCancelCurrentAction); 0676 0677 // 0678 d->ui.kClearMessageBtn->setIcon(SKGServices::fromTheme(QStringLiteral("edit-clear"))); 0679 connect(d->ui.kClearMessageBtn, &QPushButton::clicked, this, &SKGMainPanel::onClearMessages); 0680 0681 // Add special button in toolbar 0682 KToolBar* tb = toolBar(); 0683 if (tb != nullptr) { 0684 auto label = new QLabel(this); 0685 QSizePolicy sizePolicyLabel(QSizePolicy::Expanding, QSizePolicy::Preferred); 0686 sizePolicyLabel.setHorizontalStretch(0); 0687 sizePolicyLabel.setVerticalStretch(0); 0688 sizePolicyLabel.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); 0689 label->setSizePolicy(sizePolicyLabel); 0690 tb->addWidget(label); 0691 tb->addAction(d->m_buttonMenuAction); 0692 } 0693 0694 statusBar()->addPermanentWidget(kCancelButton); 0695 statusBar()->addPermanentWidget(d->m_zoomSelector); 0696 0697 // Set progress bar call back 0698 if (getDocument() != nullptr) { 0699 d->m_progressObjects.p1 = static_cast<void*>(kProgressBar); 0700 d->m_progressObjects.p2 = static_cast<void*>(kCancelButton); 0701 getDocument()->setProgressCallback(&SKGMainPanelPrivate::progressBarCallBack, static_cast<void*>(&d->m_progressObjects)); 0702 } 0703 0704 // Connection 0705 if (getDocument() != nullptr) { 0706 connect(getDocument(), &SKGDocument::transactionSuccessfullyEnded, this, &SKGMainPanel::refresh, Qt::QueuedConnection); 0707 connect(getDocument(), &SKGDocument::transactionSuccessfullyEnded, this, &SKGMainPanel::notify, Qt::QueuedConnection); 0708 } 0709 connect(d->ui.kContextList, &QListWidget::itemPressed, this, &SKGMainPanel::onBeforeOpenContext); 0710 connect(d->ui.kContextList, &QListWidget::itemPressed, this, &SKGMainPanel::onOpenContext); 0711 connect(d->m_tabWidget->tabBar(), &QTabBar::tabCloseRequested, this, &SKGMainPanel::closePageByIndex); 0712 connect(d->m_tabWidget->tabBar(), &QTabBar::tabBarClicked, this, [ = ](int index) { 0713 if ((QApplication::mouseButtons() & Qt::MidButton) != 0u) { 0714 closePageByIndex(index); 0715 } 0716 }); 0717 connect(d->m_tabWidget->tabBar(), &QTabBar::tabBarDoubleClicked, this, &SKGMainPanel::addTab); 0718 connect(d->m_tabWidget->tabBar(), &QTabBar::currentChanged, this, &SKGMainPanel::currentPageChanged); 0719 connect(this, &SKGMainPanel::currentPageChanged, this, &SKGMainPanel::refresh); 0720 connect(this, &SKGMainPanel::currentPageChanged, this, &SKGMainPanel::selectionChanged); 0721 0722 // Refresh 0723 refresh(); 0724 0725 d->ui.kContextList->installEventFilter(this); 0726 0727 // Build contextual menu 0728 d->ui.kContextList->setContextMenuPolicy(Qt::CustomContextMenu); 0729 0730 d->m_contextMenu = new QMenu(d->ui.kContextList); 0731 d->m_actHideContextItem = d->m_contextMenu->addAction(SKGServices::fromTheme(QStringLiteral("layer-visible-off")), i18nc("Verb", "Hide")); 0732 connect(d->m_actHideContextItem, &QAction::triggered, this, &SKGMainPanel::onHideContextItem); 0733 0734 d->m_actShowAllContextItems = d->m_contextMenu->addAction(SKGServices::fromTheme(QStringLiteral("layer-visible-on")), i18nc("Verb", "Show all")); 0735 connect(d->m_actShowAllContextItems, &QAction::triggered, this, &SKGMainPanel::onShowAllContextItems); 0736 0737 d->m_contextMenu->addSeparator(); 0738 d->m_contextMenu->addAction(getGlobalAction(QStringLiteral("tab_savedefaultstate"))); 0739 d->m_contextMenu->addAction(getGlobalAction(QStringLiteral("tab_resetdefaultstate"))); 0740 0741 connect(d->ui.kContextList, &QListWidget::customContextMenuRequested, this, &SKGMainPanel::showMenu); 0742 0743 #ifdef KActivities_FOUND 0744 // Initialize kactivities resource instance 0745 d->m_activityResourceInstance = new KActivities::ResourceInstance(window()->winId()); 0746 d->m_activityResourceInstance->setParent(this); 0747 #endif 0748 0749 // Show menu bar and status bar 0750 menuBar()->show(); 0751 statusBar()->show(); 0752 0753 notify(); // Due to sendMessage not in a transaction 0754 d->m_splashScreen = nullptr; 0755 } 0756 0757 SKGMainPanel::~SKGMainPanel() 0758 { 0759 SKGTRACEINFUNC(1) 0760 SKGMainPanelPrivate::m_mainPanel = nullptr; 0761 disconnect(getDocument(), nullptr, this, nullptr); 0762 0763 // close plugins 0764 int nb = d->m_pluginsList.count(); 0765 for (int i = 0; i < nb; ++i) { 0766 auto plugin = getPluginByIndex(i); 0767 plugin->close(); 0768 } 0769 0770 if (getDocument() != nullptr) { 0771 getDocument()->close(); 0772 } 0773 delete d; 0774 } 0775 0776 void SKGMainPanel::showMenu(const QPoint iPos) 0777 { 0778 if (d->m_contextMenu != nullptr) { 0779 d->m_contextMenu->popup(d->ui.kContextList->mapToGlobal(iPos)); 0780 } 0781 } 0782 0783 void SKGMainPanel::setContextVisibility(QListWidgetItem* iItem, bool iVisibility) 0784 { 0785 if (iItem != nullptr) { 0786 // Hide item in context 0787 iItem->setHidden(!iVisibility); 0788 0789 // Hide corresponding action 0790 QAction* act = static_cast< QAction* >(iItem->data(15).value<void*>()); 0791 if (act != nullptr) { 0792 act->setVisible(iVisibility); 0793 } 0794 0795 // Save state in settings 0796 SKGInterfacePlugin* plugin = getPluginByIndex(iItem->data(12).toInt()); 0797 if (plugin != nullptr) { 0798 KSharedConfigPtr config = KSharedConfig::openConfig(); 0799 KConfigGroup pref = config->group("Context Visibility"); 0800 pref.writeEntry(plugin->objectName(), iVisibility); 0801 } 0802 } 0803 } 0804 0805 void SKGMainPanel::setContextVisibility(int iPage, bool iVisibility) 0806 { 0807 setContextVisibility(d->ui.kContextList->item(iPage), iVisibility); 0808 } 0809 0810 void SKGMainPanel::onHideContextItem() 0811 { 0812 setContextVisibility(d->ui.kContextList->currentRow(), false); 0813 } 0814 0815 void SKGMainPanel::onShowAllContextItems() 0816 { 0817 int nb = d->ui.kContextList->count(); 0818 for (int i = 0; i < nb; ++i) { 0819 setContextVisibility(i, true); 0820 } 0821 } 0822 0823 SKGDocument* SKGMainPanel::getDocument() const 0824 { 0825 return d->m_currentDocument; 0826 } 0827 0828 QStringList SKGMainPanel::processArguments(const QStringList& iArgument) 0829 { 0830 QStringList output = iArgument; 0831 for (auto plugin : qAsConst(d->m_pluginsList)) { 0832 if (plugin != nullptr) { 0833 output = plugin->processArguments(output); 0834 } 0835 } 0836 return output; 0837 } 0838 0839 void SKGMainPanel::registerGlobalAction(const QString& iIdentifier, QAction* iAction, bool iAddInCollection, 0840 const QStringList& iListOfTable, int iMinSelection, int iMaxSelection, 0841 int iRanking, bool iSelectionMustHaveFocus) 0842 { 0843 if (iAction == nullptr) { 0844 SKGTRACE << "WARNING: registerGlobalAction(" << iIdentifier << ",nullptr)" << SKGENDL; 0845 } else { 0846 if (d->m_registeredGlogalAction.contains(iIdentifier) && 0847 d->m_registeredGlogalAction.value(iIdentifier).action != iAction) { 0848 SKGTRACE << "WARNING: Another action already registered for identifier " << iIdentifier << SKGENDL; 0849 } 0850 QStringList keys = d->m_registeredGlogalAction.keys(); 0851 for (const auto& id : qAsConst(keys)) { 0852 QPointer<QAction> act = d->m_registeredGlogalAction.value(id).action; 0853 if ((act != nullptr) && iIdentifier != id && act != iAction && !act->shortcut().isEmpty() && act->shortcut() == iAction->shortcut()) { 0854 SKGTRACE << "WARNING: The actions [" << iAction->text() << " (" << iIdentifier << ")] and [" << act->text() << " (" << id << ")] has same shortcut [" << iAction->shortcut().toString() << "]" << SKGENDL; 0855 } 0856 } 0857 actionDetails actDetails; 0858 actDetails.action = iAction; 0859 actDetails.tables = iListOfTable; 0860 actDetails.min = iMinSelection; 0861 actDetails.max = iMaxSelection; 0862 actDetails.focus = iSelectionMustHaveFocus; 0863 actDetails.ranking = (iRanking == -1 ? 10 * (d->m_registeredGlogalAction.count() + 1) : iRanking); 0864 d->m_registeredGlogalAction[iIdentifier] = actDetails; 0865 0866 // This connect has not been migrated on new connect mechanism to avoid crash when leaving the application 0867 connect(iAction, SIGNAL(destroyed(QObject*)), this, SLOT(unRegisterGlobalAction(QObject*))); // clazy:exclude=old-style-connect 0868 if (iAddInCollection) { 0869 QKeySequence shortCut = iAction->shortcut(); 0870 if (!shortCut.isEmpty()) { 0871 iAction->setShortcut(QKeySequence()); 0872 } 0873 actionCollection()->addAction(iIdentifier, iAction); 0874 if (!shortCut.isEmpty()) { 0875 actionCollection()->setDefaultShortcut(iAction, shortCut); 0876 } 0877 } 0878 } 0879 } 0880 0881 void SKGMainPanel::unRegisterGlobalAction(QObject* iAction) 0882 { 0883 auto* act = qobject_cast< QAction* >(iAction); 0884 if (act != nullptr) { 0885 const auto keys = d->m_registeredGlogalAction.keys(); 0886 for (const auto& id : keys) { 0887 if (d->m_registeredGlogalAction.value(id).action == QPointer<QAction>(act)) { 0888 d->m_registeredGlogalAction.remove(id); 0889 } 0890 } 0891 } 0892 } 0893 0894 QPointer<QAction> SKGMainPanel::getGlobalAction(const QString& iIdentifier, bool iWarnIfNotExist) 0895 { 0896 QAction* act = d->m_registeredGlogalAction.value(iIdentifier).action; 0897 if (act == nullptr && iWarnIfNotExist) { 0898 SKGTRACE << "WARNING: getGlobalAction(" << iIdentifier << ")=nullptr" << SKGENDL; 0899 } 0900 return act; 0901 } 0902 0903 QList< QPointer< QAction > > SKGMainPanel::getActionsForContextualMenu(const QString& iTable) 0904 { 0905 // Filter action 0906 QVector<actionDetails> tmp; 0907 for (const auto& actDetails : qAsConst(d->m_registeredGlogalAction)) { 0908 if (actDetails.ranking > 0 && actDetails.min > 0) { 0909 if (actDetails.tables.isEmpty() || actDetails.tables.contains(iTable)) { 0910 tmp.push_back(actDetails); 0911 } else if (actDetails.tables.count() == 1 && actDetails.tables.at(0).startsWith(QLatin1String("query:"))) { 0912 // Dynamic mode 0913 QStringList tmpListTable; 0914 getDocument()->getDistinctValues(QStringLiteral("sqlite_master"), QStringLiteral("name"), actDetails.tables.at(0).right(actDetails.tables.at(0).count() - 6), tmpListTable); 0915 if (tmpListTable.contains(iTable)) { 0916 tmp.push_back(actDetails); 0917 } 0918 } 0919 } 0920 } 0921 0922 // Sort 0923 std::sort(tmp.begin(), tmp.end(), [&](const actionDetails & a, const actionDetails & b) { 0924 return a.ranking < b.ranking; 0925 }); 0926 0927 // Generate output 0928 int previousGroup = -1; 0929 QList< QPointer< QAction > > output; 0930 output.reserve(tmp.count()); 0931 for (const auto& actDetails : qAsConst(tmp)) { 0932 int currentGroup = (actDetails.ranking) / 100; 0933 if (currentGroup != previousGroup) { 0934 output.push_back(nullptr); 0935 previousGroup = currentGroup; 0936 } 0937 output.push_back(actDetails.action); 0938 } 0939 return output; 0940 } 0941 0942 QMap<QString, QPointer<QAction> > SKGMainPanel::getGlobalActions() const 0943 { 0944 QMap<QString, QPointer<QAction> > map; 0945 const auto keys = d->m_registeredGlogalAction.keys(); 0946 for (const auto& id : keys) { 0947 map[id] = d->m_registeredGlogalAction[id].action; 0948 } 0949 return map; 0950 } 0951 0952 SKGInterfacePlugin* SKGMainPanel::getPluginByIndex(int iIndex) 0953 { 0954 SKGInterfacePlugin* output = nullptr; 0955 if (iIndex >= 0 && iIndex < d->m_pluginsList.count()) { 0956 output = d->m_pluginsList.value(iIndex); 0957 } 0958 0959 return output; 0960 } 0961 0962 SKGInterfacePlugin* SKGMainPanel::getPluginByName(const QString& iName) 0963 { 0964 SKGInterfacePlugin* output = nullptr; 0965 int nbplugin = d->m_pluginsList.count(); 0966 QString name = iName.toLower(); 0967 for (int j = 0; (output == nullptr) && j < nbplugin; ++j) { 0968 QString namep = d->m_pluginsList.at(j)->objectName().toLower(); 0969 if (namep == name || namep.replace(' ', '_') == name) { 0970 output = d->m_pluginsList.at(j); 0971 } 0972 } 0973 0974 return output; 0975 } 0976 0977 void SKGMainPanel::setupActions() 0978 { 0979 SKGTRACEINFUNC(1) 0980 0981 // Std File 0982 KStandardAction::quit(this, SLOT(onQuitAction()), actionCollection()); 0983 KStandardAction::configureNotifications(this, SLOT(onConfigureNotifications()), actionCollection()); 0984 0985 // Preferences 0986 KStandardAction::preferences(this, SLOT(optionsPreferences()), actionCollection()); 0987 0988 // New Tab 0989 auto actAddTab = new QAction(SKGServices::fromTheme(QStringLiteral("tab-new-background")), i18nc("Noun, user action", "New Tab"), this); 0990 actionCollection()->setDefaultShortcut(actAddTab, Qt::CTRL + Qt::SHIFT + Qt::Key_W); 0991 connect(actAddTab, &QAction::triggered, this, &SKGMainPanel::addTab); 0992 registerGlobalAction(QStringLiteral("new_tab"), actAddTab, true, QStringList(), -1); 0993 0994 // Add new tab widget 0995 auto addTabButton = new QToolButton(this); 0996 addTabButton->setIcon(actAddTab->icon()); 0997 addTabButton->setAutoRaise(true); 0998 addTabButton->raise(); 0999 addTabButton->setDefaultAction(actAddTab); 1000 addTabButton->setToolButtonStyle(Qt::ToolButtonIconOnly); 1001 addTabButton->setFocusPolicy(Qt::NoFocus); 1002 d->m_tabWidget->setCornerWidget(addTabButton); 1003 1004 d->m_actLock = new QAction(SKGServices::fromTheme(QStringLiteral("document-encrypt")), i18nc("Verb", "Lock panels"), this); 1005 connect(d->m_actLock, &QAction::triggered, this, &SKGMainPanel::onLockDocks); 1006 registerGlobalAction(QStringLiteral("view_lock"), d->m_actLock); 1007 1008 d->m_actUnLock = new QAction(SKGServices::fromTheme(QStringLiteral("document-decrypt")), i18nc("Verb", "Unlock panels"), this); 1009 connect(d->m_actUnLock, &QAction::triggered, this, &SKGMainPanel::onUnlockDocks); 1010 registerGlobalAction(QStringLiteral("view_unlock"), d->m_actUnLock); 1011 1012 d->m_switchPinState = new QAction(SKGServices::fromTheme(QStringLiteral("document-encrypt")), i18nc("Noun, user action", "Pin this page"), this); 1013 connect(d->m_switchPinState, &QAction::triggered, this, [ = ] {this->switchPinPage(nullptr);}); 1014 registerGlobalAction(QStringLiteral("tab_switchpin"), d->m_switchPinState); 1015 1016 // 1017 d->m_closePageAction = actionCollection()->addAction(KStandardAction::Close, QStringLiteral("tab_close"), this, SLOT(closeCurrentPage())); 1018 registerGlobalAction(QStringLiteral("tab_close"), d->m_closePageAction); 1019 1020 // 1021 auto actCloseAllPages = new QAction(SKGServices::fromTheme(QStringLiteral("window-close")), i18nc("Noun, user action", "Close All"), this); 1022 actionCollection()->setDefaultShortcut(actCloseAllPages, Qt::ALT + Qt::Key_W); 1023 connect(actCloseAllPages, &QAction::triggered, this, &SKGMainPanel::closeAllPages); 1024 registerGlobalAction(QStringLiteral("tab_closeall"), actCloseAllPages, true, QStringList(), -1); 1025 1026 // 1027 d->m_closeAllOtherPagesAction = new QAction(SKGServices::fromTheme(QStringLiteral("window-close")), i18nc("Noun, user action", "Close All Other"), this); 1028 actionCollection()->setDefaultShortcut(d->m_closeAllOtherPagesAction, Qt::CTRL + Qt::ALT + Qt::Key_W); 1029 connect(d->m_closeAllOtherPagesAction, &QAction::triggered, this, [ = ] {this->closeAllOtherPages(nullptr);}); 1030 registerGlobalAction(QStringLiteral("tab_closeallother"), d->m_closeAllOtherPagesAction); 1031 1032 // 1033 d->m_saveDefaultStateAction = new QAction(SKGServices::fromTheme(QStringLiteral("document-save")), i18nc("Noun, user action", "Save page state"), this); 1034 actionCollection()->setDefaultShortcut(d->m_saveDefaultStateAction, Qt::CTRL + Qt::ALT + Qt::Key_S); 1035 connect(d->m_saveDefaultStateAction, &QAction::triggered, this, &SKGMainPanel::saveDefaultState); 1036 registerGlobalAction(QStringLiteral("tab_savedefaultstate"), d->m_saveDefaultStateAction); 1037 1038 // 1039 d->m_resetDefaultStateAction = new QAction(SKGServices::fromTheme(QStringLiteral("edit-clear")), i18nc("Noun, user action", "Reset page state"), this); 1040 actionCollection()->setDefaultShortcut(d->m_resetDefaultStateAction, Qt::CTRL + Qt::ALT + Qt::Key_R); 1041 connect(d->m_resetDefaultStateAction, &QAction::triggered, this, &SKGMainPanel::resetDefaultState); 1042 registerGlobalAction(QStringLiteral("tab_resetdefaultstate"), d->m_resetDefaultStateAction); 1043 1044 // 1045 d->m_reopenLastClosed = new QAction(SKGServices::fromTheme(QStringLiteral("tab-new")), i18nc("Noun, user action", "Reopen last page closed"), this); 1046 actionCollection()->setDefaultShortcut(d->m_reopenLastClosed, Qt::CTRL + Qt::ALT + Qt::Key_T); 1047 connect(d->m_reopenLastClosed, &QAction::triggered, this, &SKGMainPanel::onReopenLastClosed); 1048 registerGlobalAction(QStringLiteral("tab_reopenlastclosed"), d->m_reopenLastClosed); 1049 1050 // 1051 QStringList overlay; 1052 overlay.push_back(QStringLiteral("bookmarks")); 1053 d->m_overwriteBookmarkStateAction = new QAction(SKGServices::fromTheme(QStringLiteral("document-save"), overlay), i18nc("Noun, user action", "Overwrite bookmark state"), this); 1054 connect(d->m_overwriteBookmarkStateAction, &QAction::triggered, this, &SKGMainPanel::overwriteBookmarkState); 1055 actionCollection()->setDefaultShortcut(d->m_overwriteBookmarkStateAction, Qt::CTRL + Qt::ALT + Qt::Key_B); 1056 registerGlobalAction(QStringLiteral("tab_overwritebookmark"), d->m_overwriteBookmarkStateAction); 1057 1058 // 1059 d->m_configureAction = new QAction(SKGServices::fromTheme(QStringLiteral("configure")), i18nc("Noun, user action", "Configure…"), this); 1060 connect(d->m_configureAction, &QAction::triggered, this, [ = ] {this->optionsPreferences();}); 1061 registerGlobalAction(QStringLiteral("tab_configure"), d->m_configureAction); 1062 1063 // Menu 1064 d->m_buttonMenuAction = new KToolBarPopupAction(SKGServices::fromTheme(QStringLiteral("configure")), QLatin1String(""), this); 1065 d->m_buttonMenuAction->setToolTip(i18nc("Noun, user action", "Menu")); 1066 d->m_buttonMenu = d->m_buttonMenuAction->menu(); 1067 connect(d->m_buttonMenu, &QMenu::aboutToShow, this, &SKGMainPanel::onShowButtonMenu); 1068 d->m_buttonMenuAction->setDelayed(false); 1069 registerGlobalAction(QStringLiteral("view_menu"), d->m_buttonMenuAction); 1070 1071 d->m_showMenuBarAction = KStandardAction::showMenubar(this, SLOT(onShowMenuBar()), actionCollection()); 1072 KConfigGroup pref = getMainConfigGroup(); 1073 d->m_showMenuBarAction->setChecked(pref.readEntry("menubar_shown", true)); 1074 QTimer::singleShot(200, Qt::CoarseTimer, this, &SKGMainPanel::onShowMenuBar); 1075 registerGlobalAction(QStringLiteral("options_show_menubar"), d->m_showMenuBarAction); 1076 1077 // 1078 d->m_previousAction = new KToolBarPopupAction(SKGServices::fromTheme(QStringLiteral("go-previous")), i18nc("Noun, user action", "Previous"), this); 1079 connect(d->m_previousAction, &QAction::triggered, this, &SKGMainPanel::onPrevious); 1080 actionCollection()->setDefaultShortcut(d->m_previousAction, Qt::ALT + Qt::Key_Left); 1081 d->m_previousAction->setPriority(QAction::LowPriority); 1082 d->m_previousMenu = d->m_previousAction->menu(); 1083 connect(d->m_previousMenu, &QMenu::aboutToShow, this, &SKGMainPanel::onShowPreviousMenu); 1084 d->m_previousAction->setStickyMenu(false); 1085 d->m_previousAction->setData(0); 1086 registerGlobalAction(QStringLiteral("go_previous"), d->m_previousAction); 1087 1088 // 1089 d->m_nextAction = new KToolBarPopupAction(SKGServices::fromTheme(QStringLiteral("go-next")), i18nc("Noun, user action", "Next"), this); 1090 connect(d->m_nextAction, &QAction::triggered, this, &SKGMainPanel::onNext); 1091 actionCollection()->setDefaultShortcut(d->m_nextAction, Qt::ALT + Qt::Key_Right); 1092 d->m_nextAction->setPriority(QAction::LowPriority); 1093 d->m_nextMenu = d->m_nextAction->menu(); 1094 connect(d->m_nextMenu, &QMenu::aboutToShow, this, &SKGMainPanel::onShowNextMenu); 1095 d->m_nextAction->setStickyMenu(false); 1096 d->m_nextAction->setData(0); 1097 registerGlobalAction(QStringLiteral("go_next"), d->m_nextAction); 1098 1099 // 1100 d->m_fullScreenAction = actionCollection()->addAction(KStandardAction::FullScreen, QStringLiteral("fullscreen"), this, SLOT(onFullScreen())); 1101 registerGlobalAction(QStringLiteral("fullscreen"), d->m_fullScreenAction); 1102 1103 // 1104 d->m_enableEditorAction = new QAction(SKGServices::fromTheme(QStringLiteral("appointment-new")), i18nc("Noun, user action", "Enable editor"), this); 1105 actionCollection()->setDefaultShortcut(d->m_enableEditorAction, Qt::CTRL + Qt::Key_Insert); 1106 connect(d->m_enableEditorAction, &QAction::triggered, this, &SKGMainPanel::enableEditor); 1107 registerGlobalAction(QStringLiteral("enable_editor"), d->m_enableEditorAction); 1108 1109 // 1110 auto migrateSQLCipher = new QAction(SKGServices::fromTheme(QStringLiteral("run-build")), i18nc("Noun, user action", "Migrate to SQLCipher format"), this); 1111 connect(migrateSQLCipher, &QAction::triggered, this, &SKGMainPanel::onMigrateToSQLCipher); 1112 registerGlobalAction(QStringLiteral("migrate_sqlcipher"), migrateSQLCipher); 1113 1114 // Contextual menu 1115 d->m_tabWidget->setContextMenuPolicy(Qt::ActionsContextMenu); 1116 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("new_tab"))); 1117 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_reopenlastclosed"))); 1118 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_close"))); 1119 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_closeall"))); 1120 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_closeallother"))); 1121 { 1122 auto sep = new QAction(this); 1123 sep->setSeparator(true); 1124 d->m_tabWidget->insertAction(nullptr, sep); 1125 } 1126 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_switchpin"))); 1127 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_resetdefaultstate"))); 1128 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_savedefaultstate"))); 1129 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_overwritebookmark"))); 1130 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_configure"))); 1131 { 1132 auto sep = new QAction(this); 1133 sep->setSeparator(true); 1134 d->m_tabWidget->insertAction(nullptr, sep); 1135 } 1136 d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("fullscreen"))); 1137 } 1138 1139 void SKGMainPanel::enableEditor() 1140 { 1141 SKGTabPage* cPage = currentPage(); 1142 if (cPage != nullptr) { 1143 cPage->activateEditor(); 1144 } 1145 } 1146 1147 void SKGMainPanel::onPrevious() 1148 { 1149 SKGError err; 1150 SKGTRACEINFUNCRC(10, err) 1151 1152 SKGTabPage* cPage = currentPage(); 1153 if (cPage != nullptr) { 1154 // Get index in history of page to refresh 1155 int indexPrevious = qobject_cast<QAction*>(sender())->data().toInt(); 1156 1157 // Get lists 1158 SKGTabPage::SKGPageHistoryItemList listPrevious = cPage->getPreviousPages(); 1159 if (indexPrevious < listPrevious.count()) { 1160 SKGTabPage::SKGPageHistoryItemList listNext = cPage->getNextPages(); 1161 SKGTabPage::SKGPageHistoryItem current = currentPageHistoryItem(); 1162 1163 // Get item to refresh 1164 SKGTabPage::SKGPageHistoryItem item = listPrevious.at(indexPrevious); 1165 1166 // Open page 1167 cPage = openPage(getPluginByName(item.plugin), currentPageIndex(), item.state, item.name, item.bookmarkID); 1168 if (cPage != nullptr) { 1169 cPage->setBookmarkID(item.bookmarkID); 1170 1171 // Update lists 1172 listNext.insert(0, current); 1173 listPrevious.removeAt(indexPrevious); 1174 for (int i = 0; i < indexPrevious; ++i) { 1175 SKGTabPage::SKGPageHistoryItem itemPrevious = listPrevious.at(0); // Because the list is modified 1176 listNext.insert(0, itemPrevious); 1177 listPrevious.removeAt(0); 1178 } 1179 1180 // Set lists 1181 cPage->setPreviousPages(listPrevious); 1182 cPage->setNextPages(listNext); 1183 } 1184 1185 refresh(); 1186 } 1187 } 1188 } 1189 1190 void SKGMainPanel::onShowPreviousMenu() 1191 { 1192 if (d->m_previousMenu != nullptr) { 1193 d->m_previousMenu->clear(); 1194 1195 SKGTabPage* cPage = currentPage(); 1196 if (cPage != nullptr) { 1197 SKGTabPage::SKGPageHistoryItemList list = cPage->getPreviousPages(); 1198 int nb = list.count(); 1199 for (int i = 0; i < nb; ++i) { 1200 QAction* act = d->m_previousMenu->addAction(SKGServices::fromTheme(list.at(i).icon), list.at(i).name); 1201 if (act != nullptr) { 1202 act->setData(i); 1203 connect(act, &QAction::triggered, this, &SKGMainPanel::onPrevious); 1204 } 1205 } 1206 } 1207 } 1208 } 1209 1210 void SKGMainPanel::onShowMenuBar() 1211 { 1212 bool test = d->m_showMenuBarAction->isChecked(); 1213 menuBar()->setVisible(test); 1214 d->m_buttonMenuAction->setVisible(!test); 1215 1216 KConfigGroup pref = getMainConfigGroup(); 1217 pref.writeEntry("menubar_shown", test); 1218 } 1219 1220 void SKGMainPanel::onFullScreen() 1221 { 1222 auto* p = d->m_tabWidget; 1223 if (p != nullptr) { 1224 if (!d->m_fullScreenAction->isChecked()) { 1225 // No Full screen 1226 p->setWindowState(p->windowState() & ~Qt::WindowFullScreen); // reset 1227 d->m_mainLayout->addWidget(d->m_tabWidget); 1228 } else { 1229 bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); 1230 if (atLeastOnePageOpened) { 1231 // Activate Full screen mode 1232 p->setParent(nullptr); 1233 p->setWindowFlags(p->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); 1234 p->setWindowState(p->windowState() | Qt::WindowFullScreen); // set 1235 p->show(); 1236 1237 displayMessage(i18nc("Information message", "You can exit full screen mode with %1 or with the contextual menu", d->m_fullScreenAction->shortcut().toString())); 1238 } else { 1239 d->m_fullScreenAction->setChecked(false); 1240 displayMessage(i18nc("Information message", "At least one page must be opened to enable full screen mode"), SKGDocument::Error); 1241 } 1242 } 1243 } 1244 } 1245 1246 void SKGMainPanel::onNext() 1247 { 1248 SKGError err; 1249 SKGTRACEINFUNCRC(10, err) 1250 1251 SKGTabPage* cPage = currentPage(); 1252 if (cPage != nullptr) { 1253 // Get index in history of page to refresh 1254 int posNext = qobject_cast<QAction*>(sender())->data().toInt(); 1255 1256 // Get lists 1257 SKGTabPage::SKGPageHistoryItemList listPrevious = cPage->getPreviousPages(); 1258 SKGTabPage::SKGPageHistoryItemList listNext = cPage->getNextPages(); 1259 SKGTabPage::SKGPageHistoryItem current = currentPageHistoryItem(); 1260 1261 // Get item to refresh 1262 SKGTabPage::SKGPageHistoryItem item = listNext.at(posNext); 1263 1264 // Open page 1265 cPage = openPage(getPluginByName(item.plugin), currentPageIndex(), item.state, item.name, item.bookmarkID); 1266 if (cPage != nullptr) { 1267 cPage->setBookmarkID(item.bookmarkID); 1268 1269 // Update lists 1270 listPrevious.insert(0, current); 1271 listNext.removeAt(posNext); 1272 for (int i = 0; i < posNext; ++i) { 1273 SKGTabPage::SKGPageHistoryItem itemNext = listNext.at(0); // Because the list is modified 1274 listPrevious.insert(0, itemNext); 1275 listNext.removeAt(0); 1276 } 1277 1278 // Set lists 1279 cPage->setPreviousPages(listPrevious); 1280 cPage->setNextPages(listNext); 1281 } 1282 1283 refresh(); 1284 } 1285 } 1286 1287 void SKGMainPanel::onReopenLastClosed() 1288 { 1289 SKGError err; 1290 SKGTRACEINFUNCRC(10, err) 1291 1292 SKGTabPage::SKGPageHistoryItem current = currentPageHistoryItem(); 1293 1294 // Get item to refresh 1295 historyPage item = d->m_historyClosedPages.takeLast(); 1296 1297 // Open page 1298 SKGTabPage* cPage = openPage(getPluginByName(item.current.plugin), -1, item.current.state, item.current.name, item.current.bookmarkID); 1299 if (cPage != nullptr) { 1300 cPage->setBookmarkID(item.current.bookmarkID); 1301 cPage->setNextPages(item.next); 1302 cPage->setPreviousPages(item.previous); 1303 } 1304 1305 refresh(); 1306 } 1307 1308 void SKGMainPanel::onLockDocks() 1309 { 1310 QObjectList cs = children(); 1311 for (auto c : qAsConst(cs)) { 1312 auto* doc = qobject_cast<QDockWidget*>(c); 1313 if (doc != nullptr) { 1314 doc->setFeatures(QDockWidget::NoDockWidgetFeatures); 1315 } 1316 } 1317 1318 KConfigGroup pref = getMainConfigGroup(); 1319 pref.writeEntry("docks_locked", true); 1320 1321 refresh(); 1322 } 1323 1324 void SKGMainPanel::onUnlockDocks() 1325 { 1326 QObjectList cs = children(); 1327 for (auto c : qAsConst(cs)) { 1328 auto* doc = qobject_cast<QDockWidget*>(c); 1329 if (doc != nullptr) { 1330 doc->setFeatures(QDockWidget::AllDockWidgetFeatures); 1331 } 1332 } 1333 1334 KConfigGroup pref = getMainConfigGroup(); 1335 pref.writeEntry("docks_locked", false); 1336 1337 refresh(); 1338 } 1339 1340 void SKGMainPanel::onConfigureNotifications() 1341 { 1342 KNotifyConfigWidget::configure(this); 1343 } 1344 1345 void SKGMainPanel::onShowNextMenu() 1346 { 1347 if (d->m_nextMenu != nullptr) { 1348 d->m_nextMenu->clear(); 1349 1350 SKGTabPage* cPage = currentPage(); 1351 if (cPage != nullptr) { 1352 SKGTabPage::SKGPageHistoryItemList list = cPage->getNextPages(); 1353 int nb = list.count(); 1354 for (int i = 0; i < nb; ++i) { 1355 QAction* act = d->m_nextMenu->addAction(SKGServices::fromTheme(list.at(i).icon), list.at(i).name); 1356 if (act != nullptr) { 1357 act->setData(i); 1358 connect(act, &QAction::triggered, this, &SKGMainPanel::onNext); 1359 } 1360 } 1361 } 1362 } 1363 } 1364 1365 void SKGMainPanel::onShowButtonMenu() 1366 { 1367 if (d->m_buttonMenu != nullptr) { 1368 d->m_buttonMenu->clear(); 1369 1370 QMenuBar* mb = menuBar(); 1371 if (mb != nullptr) { 1372 d->m_buttonMenu->addActions(mb->actions()); 1373 } 1374 } 1375 } 1376 1377 bool SKGMainPanel::queryClose() 1378 { 1379 SKGTRACEINFUNC(1) 1380 // Bug 2777697: To be sure that all page modifications are closed 1381 closeAllPages(); 1382 // Bug 2777697: 1383 1384 bool output = queryFileClose(); 1385 1386 // To be sure that the application is not closed in fullscreen mode 1387 if (output) { 1388 if (d->m_fullScreenAction->isChecked()) { 1389 d->m_fullScreenAction->trigger(); 1390 } 1391 } 1392 1393 return output; 1394 } 1395 1396 void SKGMainPanel::setSaveOnClose(bool iSaveOnClose) 1397 { 1398 d->m_saveOnClose = iSaveOnClose; 1399 } 1400 1401 bool SKGMainPanel::queryFileClose() 1402 { 1403 SKGTRACEINFUNC(1) 1404 bool output = true; 1405 if (getDocument()->getCurrentTransaction() != 0) { 1406 displayMessage(i18nc("skgtestimportskg", "The application cannot be closed when a transaction is running."), SKGDocument::Error); 1407 output = false; 1408 } else if (getDocument()->isFileModified()) { 1409 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 1410 #ifdef SKG_KF_5102 1411 int code = KMessageBox::PrimaryAction; 1412 #else 1413 int code = KMessageBox::Yes; 1414 #endif 1415 QString fileName = getDocument()->getCurrentFileName(); 1416 QAction* save = getGlobalAction(fileName.isEmpty() ? QStringLiteral("file_save_as") : QStringLiteral("file_save")); 1417 if (save != nullptr) { 1418 if (!d->m_saveOnClose) { 1419 #ifdef SKG_KF_5102 1420 code = KMessageBox::questionTwoActionsCancel(this, i18nc("Question", "The document has been modified.\nDo you want to save it before closing?"), 1421 QString(), 1422 KGuiItem(fileName.isEmpty() ? i18nc("Question", "Save as") : i18nc("Question", "Save"), 1423 SKGServices::fromTheme(fileName.isEmpty() ? QStringLiteral("document-save-as") : QStringLiteral("document-save"))), 1424 KGuiItem(i18nc("Question", "Do not save"))); 1425 } 1426 if (code == KMessageBox::PrimaryAction) { 1427 #else 1428 code = KMessageBox::questionYesNoCancel(this, i18nc("Question", "The document has been modified.\nDo you want to save it before closing?"), 1429 QString(), 1430 KGuiItem(fileName.isEmpty() ? i18nc("Question", "Save as") : i18nc("Question", "Save"), 1431 SKGServices::fromTheme(fileName.isEmpty() ? QStringLiteral("document-save-as") : QStringLiteral("document-save"))), 1432 KGuiItem(i18nc("Question", "Do not save"))); 1433 } 1434 if (code == KMessageBox::Yes) { 1435 #endif 1436 save->trigger(); 1437 } 1438 #ifdef SKG_KF_5102 1439 output = (code == KMessageBox::SecondaryAction || code == KMessageBox::PrimaryAction); 1440 } else { 1441 code = KMessageBox::questionTwoActions(this, i18nc("Question", "Current modifications will not be saved.\nDo you want to continue?"), 1442 i18nc("Question", "Close confirmation"), 1443 KStandardGuiItem::apply(), KStandardGuiItem::cancel() 1444 ); 1445 output = (code == KMessageBox::PrimaryAction); 1446 #else 1447 output = (code == KMessageBox::No || code == KMessageBox::Yes); 1448 } else { 1449 code = KMessageBox::questionYesNo(this, i18nc("Question", "Current modifications will not be saved.\nDo you want to continue?")); 1450 output = (code == KMessageBox::Yes); 1451 #endif 1452 } 1453 QApplication::restoreOverrideCursor(); 1454 } 1455 1456 return output; 1457 } 1458 1459 SKGObjectBase SKGMainPanel::getFirstSelectedObject() const 1460 { 1461 SKGObjectBase selection; 1462 SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); 1463 if (cPage != nullptr) { 1464 selection = cPage->getFirstSelectedObject(); 1465 } 1466 return selection; 1467 } 1468 1469 SKGObjectBase::SKGListSKGObjectBase SKGMainPanel::getSelectedObjects() const 1470 { 1471 SKGObjectBase::SKGListSKGObjectBase selection; 1472 SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); 1473 if (cPage != nullptr) { 1474 selection = cPage->getSelectedObjects(); 1475 } 1476 return selection; 1477 } 1478 1479 int SKGMainPanel::getNbSelectedObjects() const 1480 { 1481 int nb = 0; 1482 SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); 1483 if (cPage != nullptr) { 1484 nb = cPage->getNbSelectedObjects(); 1485 } 1486 return nb; 1487 } 1488 1489 bool SKGMainPanel::hasSelectionWithFocus() 1490 { 1491 bool output = false; 1492 SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); 1493 if (cPage != nullptr) { 1494 output = cPage->hasSelectionWithFocus(); 1495 } 1496 return output; 1497 } 1498 1499 SKGAdviceList SKGMainPanel::getAdvice() const 1500 { 1501 SKGTRACEINFUNC(1) 1502 // Get list of ignored advice 1503 QString currentMonth = QDate::currentDate().toString(QStringLiteral("yyyy-MM")); 1504 QStringList ignoredAdvice = getDocument()->getParameters(QStringLiteral("advice"), "t_value='I' OR t_value='I_" % currentMonth % '\''); 1505 1506 // Build the list of all advice by requesting all plugins 1507 SKGAdviceList globalAdviceList; 1508 int index = 0; 1509 while (index >= 0) { 1510 SKGInterfacePlugin* plugin = SKGMainPanel::getMainPanel()->getPluginByIndex(index); 1511 if (plugin != nullptr) { 1512 const auto list = plugin->advice(ignoredAdvice); 1513 for (const auto& ad : list) { 1514 if (!ignoredAdvice.contains(ad.getUUID()) && !ignoredAdvice.contains(SKGServices::splitCSVLine(ad.getUUID(), '|').at(0))) { 1515 globalAdviceList.push_back(ad); 1516 } 1517 } 1518 } else { 1519 index = -2; 1520 } 1521 ++index; 1522 } 1523 std::sort(globalAdviceList.begin(), globalAdviceList.end(), SKGMainPanelPrivate::adviceLessThan); 1524 1525 return globalAdviceList; 1526 } 1527 1528 KConfigGroup SKGMainPanel::getMainConfigGroup() 1529 { 1530 KSharedConfigPtr config = KSharedConfig::openConfig(); 1531 return config->group("Main Panel"); 1532 } 1533 1534 void SKGMainPanel::optionsPreferences(const QString& iPluginName) 1535 { 1536 SKGTRACEINFUNC(1) 1537 // Compute page 1538 QString pluginName = iPluginName; 1539 if (pluginName.isEmpty()) { 1540 auto* act = qobject_cast<QAction*>(sender()); 1541 if (act != nullptr) { 1542 pluginName = act->property("page").toString(); 1543 } 1544 } 1545 if (pluginName.isEmpty() && (this->currentPage() != nullptr)) { 1546 pluginName = this->currentPage()->objectName(); 1547 } 1548 SKGTRACEL(1) << "Open setting page: " << pluginName << SKGENDL; 1549 // Synchronize setting with confirmation panel 1550 if (skgbasegui_settings::update_modified_bookmarks() == 0) { 1551 KMessageBox::ButtonCode confirm; 1552 #ifdef SKG_KF_5102 1553 bool ask = KMessageBox::shouldBeShownTwoActions(QStringLiteral("updateBookmarkOnClose"), confirm); 1554 #else 1555 bool ask = KMessageBox::shouldBeShownYesNo(QStringLiteral("updateBookmarkOnClose"), confirm); 1556 #endif 1557 KConfigGroup pref = getMainConfigGroup(); 1558 if (ask) { 1559 pref.writeEntry("update_modified_bookmarks", 0, KConfigBase::Normal); 1560 SKGTRACEL(1) << "update_modified_bookmarks set to ASK" << SKGENDL; 1561 } else if (confirm == KMessageBox::Yes) { 1562 pref.writeEntry("update_modified_bookmarks", 1, KConfigBase::Normal); 1563 SKGTRACEL(1) << "update_modified_bookmarks set to ALWAYS" << SKGENDL; 1564 } else { 1565 pref.writeEntry("update_modified_bookmarks", 2, KConfigBase::Normal); 1566 SKGTRACEL(1) << "update_modified_bookmarks set to NEVER" << SKGENDL; 1567 } 1568 } 1569 1570 if (skgbasegui_settings::update_modified_contexts() == 0) { 1571 KMessageBox::ButtonCode confirm; 1572 #ifdef SKG_KF_5102 1573 bool ask = KMessageBox::shouldBeShownTwoActions(QStringLiteral("updateContextOnClose"), confirm); 1574 #else 1575 bool ask = KMessageBox::shouldBeShownYesNo(QStringLiteral("updateContextOnClose"), confirm); 1576 #endif 1577 KConfigGroup pref = getMainConfigGroup(); 1578 if (ask) { 1579 pref.writeEntry("update_modified_contexts", 0, KConfigBase::Normal); 1580 SKGTRACEL(1) << "update_modified_contexts set to ASK" << SKGENDL; 1581 } else if (confirm == KMessageBox::Yes) { 1582 pref.writeEntry("update_modified_contexts", 1, KConfigBase::Normal); 1583 SKGTRACEL(1) << "update_modified_contexts set to ALWAYS" << SKGENDL; 1584 } else { 1585 pref.writeEntry("update_modified_contexts", 2, KConfigBase::Normal); 1586 SKGTRACEL(1) << "update_modified_contexts set to NEVER" << SKGENDL; 1587 } 1588 } 1589 skgbasegui_settings::self()->load(); 1590 1591 1592 if (KConfigDialog::showDialog(QStringLiteral("settings"))) { 1593 return; 1594 } 1595 1596 auto dialog = new KConfigDialog(this, QStringLiteral("settings"), skgbasegui_settings::self()); 1597 1598 // Add main 1599 auto w = new QWidget(); 1600 d->uipref.setupUi(w); 1601 d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Short date (%1, %2)", 1602 QLocale().toString(QDate::currentDate(), QLocale::ShortFormat), 1603 QLocale().toString(QDate::currentDate().addDays(-10), QLocale::ShortFormat))); 1604 d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Long date (%1, %2)", 1605 QLocale().toString(QDate::currentDate(), QLocale::LongFormat), 1606 QLocale().toString(QDate::currentDate().addDays(-10), QLocale::LongFormat))); 1607 d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Fancy short date (%1, %2)", 1608 KFormat().formatRelativeDate(QDate::currentDate(), QLocale::ShortFormat), 1609 KFormat().formatRelativeDate(QDate::currentDate().addDays(-10), QLocale::ShortFormat))); 1610 d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Fancy long date (%1, %2)", 1611 KFormat().formatRelativeDate(QDate::currentDate(), QLocale::LongFormat), 1612 KFormat().formatRelativeDate(QDate::currentDate().addDays(-10), QLocale::LongFormat))); 1613 d->uipref.kcfg_date_format->addItem(i18nc("Date format", "ISO date (%1, %2)", 1614 QDate::currentDate().toString(Qt::ISODate), 1615 QDate::currentDate().addDays(-10).toString(Qt::ISODate))); 1616 dialog->addPage(w, skgbasegui_settings::self(), i18nc("Noun", "General"), QStringLiteral("preferences-other")); 1617 1618 // Add plugin in client in right order 1619 int nbplugin = d->m_pluginsList.count(); 1620 for (int j = 0; j < nbplugin; ++j) { 1621 SKGInterfacePlugin* pluginInterface = getPluginByIndex(j); 1622 if (pluginInterface != nullptr) { 1623 QWidget* w2 = pluginInterface->getPreferenceWidget(); 1624 if (w2 != nullptr) { 1625 auto icon = SKGServices::fromTheme(pluginInterface->icon()); 1626 KPageWidgetItem* p = dialog->addPage(w2, pluginInterface->getPreferenceSkeleton(), pluginInterface->title(), icon.name()); 1627 if ((p != nullptr) && pluginName == pluginInterface->objectName()) { 1628 dialog->setCurrentPage(p); 1629 } 1630 } 1631 } 1632 } 1633 1634 connect(dialog, &KConfigDialog::settingsChanged, this, &SKGMainPanel::onSettingsChanged); 1635 1636 dialog->setAttribute(Qt::WA_DeleteOnClose); 1637 dialog->show(); 1638 1639 // Refresh 1640 refresh(); 1641 } 1642 1643 void SKGMainPanel::onSettingsChanged() 1644 { 1645 SKGError err; 1646 SKGTRACEINFUNCRC(1, err) { 1647 int nb = d->m_pluginsList.count(); 1648 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Save settings"), err, nb) 1649 1650 // Refresh plugins 1651 for (int i = 0; !err && i < nb; ++i) { 1652 err = getPluginByIndex(i)->savePreferences(); 1653 IFOKDO(err, getDocument()->stepForward(i + 1)) 1654 } 1655 1656 // Setting for tab position 1657 d->refreshTabPosition(); 1658 1659 // Setting for bookmarks modification 1660 { 1661 int option = skgbasegui_settings::update_modified_bookmarks(); 1662 if (option == 0) { 1663 // ASK: remove following setting 1664 KMessageBox::enableMessage(QStringLiteral("updateBookmarkOnClose")); 1665 SKGTRACEL(1) << "updateBookmarkOnClose set to ASK" << SKGENDL; 1666 } else if (option == 1) { 1667 // ALWAYS: set following setting 1668 #ifdef SKG_KF_5102 1669 KMessageBox::saveDontShowAgainTwoActions(QStringLiteral("updateBookmarkOnClose"), KMessageBox::Yes); 1670 #else 1671 KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateBookmarkOnClose"), KMessageBox::No); 1672 #endif 1673 SKGTRACEL(1) << "updateBookmarkOnClose set to Yes" << SKGENDL; 1674 } else { 1675 // NEVER: set following setting 1676 #ifdef SKG_KF_5102 1677 KMessageBox::saveDontShowAgainTwoActions(QStringLiteral("updateBookmarkOnClose"), KMessageBox::No); 1678 #else 1679 KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateBookmarkOnClose"), KMessageBox::No); 1680 #endif 1681 SKGTRACEL(1) << "updateBookmarkOnClose set to No" << SKGENDL; 1682 } 1683 } 1684 { 1685 int option = skgbasegui_settings::update_modified_contexts(); 1686 if (option == 0) { 1687 // ASK: remove following setting 1688 KMessageBox::enableMessage(QStringLiteral("updateContextOnClose")); 1689 SKGTRACEL(1) << "updateContextOnClose set to ASK" << SKGENDL; 1690 } else if (option == 1) { 1691 // ALWAYS: set following setting 1692 #ifdef SKG_KF_5102 1693 KMessageBox::saveDontShowAgainTwoActions(QStringLiteral("updateContextOnClose"), KMessageBox::Yes); 1694 #else 1695 KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateBookmarkOnClose"), KMessageBox::Yes); 1696 1697 #endif 1698 SKGTRACEL(1) << "updateContextOnClose set to Yes" << SKGENDL; 1699 } else { 1700 // NEVER: set following setting 1701 #ifdef SKG_KF_5102 1702 KMessageBox::saveDontShowAgainTwoActions(QStringLiteral("updateContextOnClose"), KMessageBox::No); 1703 #else 1704 KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateContextOnClose"), KMessageBox::No); 1705 #endif 1706 SKGTRACEL(1) << "updateContextOnClose set to No" << SKGENDL; 1707 } 1708 } 1709 skgbasegui_settings::self()->load(); 1710 } 1711 1712 // Rebuild system tray 1713 d->rebuildSystemTray(); 1714 1715 emit settingsChanged(); 1716 1717 // Display error 1718 displayErrorMessage(err); 1719 } 1720 1721 void SKGMainPanel::refresh() 1722 { 1723 SKGTRACEINFUNC(1) 1724 1725 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 1726 1727 // Show/hide main widget 1728 bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); 1729 d->m_tabWidget->setVisible(atLeastOnePageOpened); 1730 if (d->m_mainWidget != nullptr) { 1731 d->m_mainWidget->setVisible(!atLeastOnePageOpened); 1732 } 1733 1734 // Refresh actions 1735 d->m_widgetHavingSelection = qobject_cast<SKGWidget*>(sender()); 1736 SKGObjectBase selection = SKGMainPanel::getMainPanel()->getFirstSelectedObject(); 1737 int nbSelectedItems = SKGMainPanel::getMainPanel()->getNbSelectedObjects(); 1738 bool hasFocus = SKGMainPanel::getMainPanel()->hasSelectionWithFocus(); 1739 1740 QString selectedTable = (nbSelectedItems > 0 ? selection.getRealTable() : QLatin1String("")); 1741 for (const auto& actDetails : qAsConst(d->m_registeredGlogalAction)) { 1742 QStringList tables = actDetails.tables; 1743 if (tables.count() == 1 && tables.at(0).startsWith(QLatin1String("query:"))) { 1744 // Dynamic mode 1745 getDocument()->getDistinctValues(QStringLiteral("sqlite_master"), QStringLiteral("name"), tables.at(0).right(tables.at(0).count() - 6), tables); 1746 } 1747 1748 bool enabled = (tables.contains(selectedTable) || tables.isEmpty()) && 1749 (nbSelectedItems >= actDetails.min) && 1750 (nbSelectedItems <= actDetails.max || actDetails.max == -1) && 1751 (!actDetails.focus || hasFocus); 1752 1753 if (enabled && nbSelectedItems == 0 && (actDetails.min == 0 || actDetails.min == -1)) { 1754 // Check if a page is opened 1755 SKGTabPage* page = SKGMainPanel::getMainPanel()->currentPage(); 1756 if (page != nullptr) { 1757 auto* view = qobject_cast<QAbstractItemView*>(page->mainWidget()); 1758 enabled = (actDetails.min == -1 || view != nullptr); 1759 } else { 1760 enabled = false; 1761 } 1762 } 1763 if (actDetails.action != nullptr) { 1764 actDetails.action->setEnabled(enabled); 1765 } 1766 } 1767 1768 // Refresh plugins 1769 int nb = d->m_pluginsList.count(); 1770 for (int i = 0; i < nb; ++i) { 1771 getPluginByIndex(i)->refresh(); 1772 } 1773 1774 // Enable addTabeAction 1775 SKGTabPage* toSave = currentPage(); 1776 if (d->m_switchPinState != nullptr) { 1777 if ((toSave != nullptr) && toSave->isPin()) { 1778 d->m_switchPinState->setText(i18nc("Noun, user action", "Unpin this page")); 1779 } else { 1780 d->m_switchPinState->setText(i18nc("Noun, user action", "Pin this page")); 1781 } 1782 } 1783 if (d->m_closePageAction != nullptr) { 1784 d->m_closePageAction->setEnabled(atLeastOnePageOpened && (toSave != nullptr) && !toSave->isPin()); 1785 } 1786 if (d->m_switchPinState != nullptr) { 1787 d->m_switchPinState->setEnabled(atLeastOnePageOpened); 1788 } 1789 if (d->m_closeAllOtherPagesAction != nullptr) { 1790 d->m_closeAllOtherPagesAction->setEnabled(d->m_tabWidget->count() > 1); 1791 } 1792 if (d->m_reopenLastClosed != nullptr) { 1793 d->m_reopenLastClosed->setEnabled(!d->m_historyClosedPages.isEmpty()); 1794 } 1795 1796 if (d->m_saveDefaultStateAction != nullptr) { 1797 d->m_saveDefaultStateAction->setEnabled((toSave != nullptr) && !toSave->getDefaultStateAttribute().isEmpty()); 1798 } 1799 if (d->m_resetDefaultStateAction != nullptr) { 1800 d->m_resetDefaultStateAction->setEnabled((toSave != nullptr) && !toSave->getDefaultStateAttribute().isEmpty()); 1801 } 1802 if (d->m_overwriteBookmarkStateAction != nullptr) { 1803 d->m_overwriteBookmarkStateAction->setEnabled((toSave != nullptr) && !toSave->getBookmarkID().isEmpty()); 1804 } 1805 if (d->m_enableEditorAction != nullptr) { 1806 d->m_enableEditorAction->setEnabled((toSave != nullptr) && toSave->isEditor()); 1807 } 1808 if (d->m_zoomSelector != nullptr) { 1809 d->m_zoomSelector->setVisible((toSave != nullptr) && toSave->isZoomable()); 1810 if (toSave != nullptr) { 1811 d->m_zoomSelector->setValue(toSave->zoomPosition()); 1812 QWidget* zoomWidget = toSave->zoomableWidget(); 1813 auto* treeView = qobject_cast<SKGTreeView*>(zoomWidget); 1814 if (treeView != nullptr) { 1815 disconnect(treeView, &SKGTreeView::zoomChanged, this, nullptr); 1816 connect(treeView, &SKGTreeView::zoomChanged, this, [ = ](int val) { 1817 d->m_zoomSelector->setValue(val); 1818 }); 1819 } else { 1820 auto* webView = qobject_cast<SKGWebView*>(zoomWidget); 1821 if (webView != nullptr) { 1822 disconnect(webView, &SKGWebView::zoomChanged, this, nullptr); 1823 connect(webView, &SKGWebView::zoomChanged, this, [ = ](int val) { 1824 d->m_zoomSelector->setValue(val); 1825 }); 1826 } 1827 } 1828 } 1829 } 1830 1831 if (d->m_actLock != nullptr) { 1832 d->m_actLock->setVisible(d->ui.kDockContext->features() == QDockWidget::AllDockWidgetFeatures); 1833 } 1834 if (d->m_actUnLock != nullptr) { 1835 d->m_actUnLock->setVisible(d->ui.kDockContext->features() == QDockWidget::NoDockWidgetFeatures); 1836 } 1837 1838 if (d->m_previousAction != nullptr) { 1839 SKGTabPage::SKGPageHistoryItemList list; 1840 if (toSave != nullptr) { 1841 list = toSave->getPreviousPages(); 1842 } 1843 d->m_previousAction->setEnabled(!list.isEmpty()); 1844 } 1845 if (d->m_nextAction != nullptr) { 1846 SKGTabPage::SKGPageHistoryItemList list; 1847 if (toSave != nullptr) { 1848 list = toSave->getNextPages(); 1849 } 1850 d->m_nextAction->setEnabled(!list.isEmpty()); 1851 } 1852 1853 // Set current selection of context 1854 d->ui.kContextList->clearSelection(); 1855 if (toSave != nullptr) { 1856 // Get plugin of current page 1857 SKGInterfacePlugin* plugin = getPluginByName(toSave->objectName()); 1858 int index = (plugin != nullptr ? plugin->property("contextItem").toInt() : -1); 1859 if (index != -1) { 1860 d->ui.kContextList->setCurrentItem(d->ui.kContextList->item(index)); 1861 } 1862 } 1863 1864 // Set window title 1865 QString modified; 1866 if (getDocument()->isFileModified()) { 1867 modified += i18nc("Noun, indicate that current document is modified", " [modified]"); 1868 } 1869 if (getDocument()->isReadOnly()) { 1870 modified += i18nc("Noun, indicate that current document is loaded in read only", " [read only]"); 1871 } 1872 QString fileName = getDocument()->getCurrentFileName(); 1873 if (fileName.isEmpty()) { 1874 fileName = i18nc("Noun, default name for a new document", "Untitled"); 1875 } else { 1876 if (fileName != d->m_fileName) { 1877 // The file name has been changed 1878 onClearMessages(); 1879 1880 d->m_fileName = fileName; 1881 #ifdef KActivities_FOUND 1882 if (!d->m_fileName.isEmpty()) { 1883 d->m_activityResourceInstance->setUri(d->m_fileName); 1884 } 1885 #endif 1886 } 1887 } 1888 setWindowTitle(i18nc("Title of the main window", "%1%2", fileName, modified)); 1889 1890 QApplication::restoreOverrideCursor(); 1891 } 1892 1893 SKGTabPage::SKGPageHistoryItem SKGMainPanel::currentPageHistoryItem() const 1894 { 1895 SKGTabPage::SKGPageHistoryItem cpage; 1896 int currentIndex = currentPageIndex(); 1897 SKGTabPage* cPage = currentPage(); 1898 if (currentIndex >= 0 && (cPage != nullptr)) { 1899 cpage.plugin = cPage->objectName(); 1900 SKGInterfacePlugin* plugin = SKGMainPanel::getMainPanel()->getPluginByName(cpage.plugin); 1901 if (plugin != nullptr) { 1902 cpage.name = d->m_tabWidget->tabText(currentIndex); 1903 cpage.icon = plugin->icon(); 1904 } 1905 cpage.state = cPage->getState(); 1906 cpage.bookmarkID = cPage->getBookmarkID(); 1907 } 1908 1909 return cpage; 1910 } 1911 1912 SKGTabPage* SKGMainPanel::openPage(SKGInterfacePlugin* plugin, int index, const QString& parameters, const QString& title, const QString& iID, bool iSetCurrent) 1913 { 1914 SKGTRACEINFUNC(1) 1915 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 1916 bool previous = d->m_tabWidget->blockSignals(true); 1917 // If the current page is pin, then open new page 1918 SKGTabPage* cPage = currentPage(); 1919 if ((cPage != nullptr) && cPage->isPin()) { 1920 index = -1; 1921 iSetCurrent = true; 1922 } 1923 1924 SKGTabPage* w = nullptr; 1925 1926 SKGTabPage::SKGPageHistoryItemList previousPages; 1927 if (index != -1) { 1928 int currentIndex = currentPageIndex(); 1929 if (currentIndex >= 0 && (cPage != nullptr)) { 1930 previousPages = cPage->getPreviousPages(); 1931 previousPages.insert(0, currentPageHistoryItem()); 1932 1933 d->m_tabWidget->removeTab(currentIndex); 1934 closePage(cPage); 1935 1936 // Repair the history of closed page 1937 if (!d->m_historyClosedPages.isEmpty()) { 1938 d->m_historyClosedPages.removeLast(); 1939 } 1940 } 1941 } 1942 1943 if (plugin != nullptr) { 1944 w = plugin->getWidget(); 1945 if (w != nullptr) { 1946 // Title 1947 QString title2 = (title.isEmpty() ? plugin->title() : title); 1948 w->setObjectName(plugin->objectName()); 1949 if (!iID.isEmpty()) { 1950 w->setBookmarkID(iID); 1951 } 1952 1953 QString param = parameters; 1954 if (param.isEmpty()) { 1955 QString def = w->getDefaultStateAttribute(); 1956 if (!def.isEmpty()) { 1957 param = getDocument()->getParameter(def); 1958 } 1959 } 1960 SKGTRACEL(10) << "state=[" << param << "]" << SKGENDL; 1961 w->setState(param); 1962 connect(w, &SKGTabPage::selectionChanged, this, &SKGMainPanel::refresh); 1963 connect(w, &SKGTabPage::selectionChanged, this, &SKGMainPanel::selectionChanged); 1964 connect(w, &SKGTabPage::selectionFocusChanged, this, &SKGMainPanel::refresh); 1965 1966 if (index == -1) { 1967 SKGTRACEINFUNC(20) 1968 d->m_tabWidget->addTab(w, SKGServices::fromTheme(plugin->icon()), title2); 1969 if (iSetCurrent) { 1970 d->m_tabWidget->setCurrentWidget(w); 1971 } 1972 } else { 1973 SKGTRACEINFUNC(20) 1974 d->m_tabWidget->insertTab(index, w, SKGServices::fromTheme(plugin->icon()), title2); 1975 if (iSetCurrent) { 1976 d->m_tabWidget->setCurrentWidget(w); 1977 } 1978 1979 w->setPreviousPages(previousPages); 1980 SKGTabPage::SKGPageHistoryItemList empty; 1981 w->setNextPages(empty); 1982 } 1983 SKGTRACEL(1) << "opening plugin [" << plugin->objectName() << ']' << SKGENDL; 1984 Q_EMIT pageOpened(); 1985 } 1986 } else { 1987 getDocument()->sendMessage(i18nc("An information message", "Impossible to open the page because the plugin was not found"), SKGDocument::Error); 1988 notify(); // Due to sendMessage not in a transaction 1989 } 1990 1991 // Show/hide main widget 1992 bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); 1993 d->m_tabWidget->setVisible(atLeastOnePageOpened); 1994 if (d->m_mainWidget != nullptr) { 1995 d->m_mainWidget->setVisible(!atLeastOnePageOpened); 1996 } 1997 1998 d->m_tabWidget->blockSignals(previous); 1999 if (iSetCurrent) { 2000 Q_EMIT currentPageChanged(); 2001 } 2002 QApplication::restoreOverrideCursor(); 2003 return w; 2004 } 2005 2006 int SKGMainPanel::currentPageIndex() const 2007 { 2008 return d->m_tabWidget->currentIndex(); 2009 } 2010 2011 SKGTabPage* SKGMainPanel::currentPage() const 2012 { 2013 return qobject_cast< SKGTabPage* >(d->m_tabWidget->currentWidget()); 2014 } 2015 2016 int SKGMainPanel::pageIndex(SKGTabPage* iPage) const 2017 { 2018 int nb = countPages(); 2019 for (int i = 0; i < nb; ++i) { 2020 if (page(i) == iPage) { 2021 return i; 2022 } 2023 } 2024 2025 return -1; 2026 } 2027 2028 QSplashScreen* SKGMainPanel::splashScreen() const 2029 { 2030 return d->m_splashScreen; 2031 } 2032 2033 int SKGMainPanel::countPages() const 2034 { 2035 return d->m_tabWidget->count(); 2036 } 2037 2038 SKGTabPage* SKGMainPanel::page(int iIndex) const 2039 { 2040 return qobject_cast<SKGTabPage*>(d->m_tabWidget->widget(iIndex)); 2041 } 2042 2043 void SKGMainPanel::setCurrentPage(int iIndex) 2044 { 2045 d->m_tabWidget->setCurrentIndex(iIndex); 2046 } 2047 2048 void SKGMainPanel::onBeforeOpenContext() 2049 { 2050 d->m_middleClick = ((QApplication::mouseButtons() & Qt::MidButton) != 0u); 2051 } 2052 2053 bool SKGMainPanel::openPage(const QUrl& iUrl, bool iNewPage) 2054 { 2055 const QUrl& url(iUrl); 2056 if (url.scheme() == QStringLiteral("skg")) { 2057 // Get plugin 2058 SKGInterfacePlugin* plugin = getPluginByName(url.host()); 2059 if (plugin != nullptr) { 2060 // Open special page 2061 SKGTabPage* w = plugin->getWidget(); 2062 if (w != nullptr) { 2063 // Create xml 2064 QString path = url.path().remove('/'); 2065 QDomDocument doc(QStringLiteral("SKGML")); 2066 doc.setContent(getDocument()->getParameter(path.isEmpty() ? w->getDefaultStateAttribute() : path)); 2067 QDomElement root = doc.documentElement(); 2068 if (root.isNull()) { 2069 root = doc.createElement(QStringLiteral("parameters")); 2070 doc.appendChild(root); 2071 } 2072 auto params = QUrlQuery(url).queryItems(); 2073 for (const auto& p : qAsConst(params)) { 2074 QString value = QUrl::fromPercentEncoding(p.second.toUtf8()); 2075 SKGMainPanelPrivate::setAttribute(root, p.first, value); 2076 } 2077 2078 // Open page 2079 openPage(plugin, iNewPage ? -1 : currentPageIndex(), doc.toString(), url.fragment()); 2080 return true; 2081 } 2082 } else { 2083 // Trigger action 2084 QAction* act = SKGMainPanel::getMainPanel()->getGlobalAction(url.host()); 2085 if (act != nullptr) { 2086 auto params = QUrlQuery(url).queryItems(); 2087 for (const auto& p : qAsConst(params)) { 2088 QString value = QUrl::fromPercentEncoding(p.second.toUtf8()); 2089 act->setProperty(p.first.toUtf8().data(), value); 2090 } 2091 2092 act->trigger(); 2093 return true; 2094 } 2095 } 2096 } else { 2097 QDesktopServices::openUrl(iUrl); 2098 return true; 2099 } 2100 displayErrorMessage(SKGError(ERR_ABORT, i18nc("Error message", "Unknown plugin or action [%1] in url [%2]", url.host(), iUrl.toString()))); 2101 2102 return false; 2103 } 2104 2105 bool SKGMainPanel::openPage() 2106 { 2107 return openPage(QString()); 2108 } 2109 2110 bool SKGMainPanel::openPage(const QString& iUrl, bool iNewPage) 2111 { 2112 // Get the url 2113 QString urlString(iUrl); 2114 if (urlString.isEmpty()) { 2115 auto* act = qobject_cast< QAction* >(sender()); 2116 if (act != nullptr) { 2117 urlString = act->data().toString(); 2118 } 2119 } 2120 2121 return openPage(QUrl(urlString), iNewPage); 2122 } 2123 2124 SKGTabPage* SKGMainPanel::openPage(int iPage, bool iNewPage) 2125 { 2126 SKGTRACEINFUNC(1) 2127 SKGTRACEL(1) << "iPage=" << iPage << SKGENDL; 2128 int index = d->ui.kContextList->item(iPage)->data(12).toInt(); 2129 return openPage(getPluginByIndex(index), iNewPage ? -1 : currentPageIndex()); 2130 } 2131 2132 void SKGMainPanel::onOpenContext() 2133 { 2134 SKGTRACEINFUNC(1) 2135 if (!(QApplication::mouseButtons() & Qt::RightButton)) { 2136 int cpage = -1; 2137 auto* s = qobject_cast<QAction*>(this->sender()); 2138 if (s != nullptr) { 2139 cpage = s->data().toInt(); 2140 } else { 2141 cpage = d->ui.kContextList->currentRow(); 2142 } 2143 if (cpage != -1) { 2144 openPage(cpage, ((QApplication::keyboardModifiers() &Qt::ControlModifier) != 0u) || d->m_middleClick || ((QGuiApplication::mouseButtons() & Qt::MidButton) != 0u)); 2145 } 2146 } 2147 d->m_middleClick = false; 2148 } 2149 2150 void SKGMainPanel::switchPinPage(QWidget* iWidget) 2151 { 2152 auto* toSwitch = qobject_cast< SKGTabPage* >(iWidget); 2153 if (toSwitch == nullptr) { 2154 toSwitch = currentPage(); 2155 } 2156 2157 if (toSwitch != nullptr) { 2158 toSwitch->setPin(!toSwitch->isPin()); 2159 Q_EMIT currentPageChanged(); 2160 } 2161 } 2162 2163 void SKGMainPanel::closePageByIndex(int iIndex) 2164 { 2165 QWidget* w = nullptr; 2166 if (iIndex >= 0) { 2167 w = d->m_tabWidget->widget(iIndex); 2168 } else { 2169 w = d->m_tabWidget->currentWidget(); 2170 } 2171 2172 closePage(w); 2173 } 2174 2175 void SKGMainPanel::closeCurrentPage() 2176 { 2177 closePage(nullptr); 2178 } 2179 2180 void SKGMainPanel::closePage(QWidget* iWidget, bool iForce) 2181 { 2182 SKGTRACEINFUNC(1) 2183 if (getDocument()->getCurrentTransaction() != 0) { 2184 QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); 2185 displayMessage(i18nc("Information message", "A page cannot be closed when a transaction is running."), SKGDocument::Information); 2186 QApplication::restoreOverrideCursor(); 2187 } else { 2188 auto* toRemove = qobject_cast< SKGTabPage* >(iWidget); 2189 if (toRemove == nullptr) { 2190 toRemove = currentPage(); 2191 } 2192 if ((toRemove != nullptr) && toRemove->close(iForce)) { 2193 historyPage item; 2194 item.current = currentPageHistoryItem(); 2195 item.next = toRemove->getNextPages(); 2196 item.previous = toRemove->getPreviousPages(); 2197 d->m_historyClosedPages.push_back(item); 2198 delete toRemove; 2199 2200 emit pageClosed(); 2201 } 2202 } 2203 2204 // Show/hide main widget 2205 bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); 2206 d->m_tabWidget->setVisible(atLeastOnePageOpened); 2207 if (d->m_mainWidget != nullptr) { 2208 d->m_mainWidget->setVisible(!atLeastOnePageOpened); 2209 } 2210 2211 if (!atLeastOnePageOpened) { 2212 d->m_fullScreenAction->setChecked(false); 2213 onFullScreen(); 2214 } 2215 } 2216 2217 void SKGMainPanel::closeAllPages(bool iForce) 2218 { 2219 SKGTRACEINFUNC(1) 2220 bool previous = d->m_tabWidget->blockSignals(true); 2221 int nb = d->m_tabWidget->count(); 2222 for (int i = nb - 1; i >= 0; --i) { 2223 auto* w = qobject_cast< SKGTabPage* >(d->m_tabWidget->widget(i)); 2224 if ((w != nullptr) && (iForce || !w->isPin())) { 2225 closePage(w, iForce); 2226 } 2227 } 2228 d->m_tabWidget->blockSignals(previous); 2229 KMessageBox::enableMessage(QStringLiteral("closepinnedpage")); 2230 Q_EMIT currentPageChanged(); 2231 } 2232 2233 void SKGMainPanel::closeAllOtherPages(QWidget* iWidget) 2234 { 2235 SKGTRACEINFUNC(1) 2236 bool previous = d->m_tabWidget->blockSignals(true); 2237 QWidget* toKeep = iWidget; 2238 if (toKeep == nullptr) { 2239 toKeep = currentPage(); 2240 } 2241 2242 int nb = d->m_tabWidget->count(); 2243 for (int i = nb - 1; i >= 0; --i) { 2244 auto* w = qobject_cast< SKGTabPage* >(d->m_tabWidget->widget(i)); 2245 if ((w != nullptr) && w != toKeep && !w->isPin()) { 2246 closePage(w); 2247 } 2248 } 2249 d->m_tabWidget->blockSignals(previous); 2250 Q_EMIT currentPageChanged(); 2251 } 2252 2253 void SKGMainPanel::saveDefaultState() 2254 { 2255 SKGTRACEINFUNC(1) 2256 SKGError err; 2257 SKGTabPage* toSave = currentPage(); 2258 if (toSave != nullptr) { 2259 // Get bookmarks uuid 2260 QString uuid = toSave->getBookmarkID(); 2261 2262 // Reset bookmarks uuid to overwrite page state 2263 toSave->setBookmarkID(QLatin1String("")); 2264 2265 // Overwrite 2266 toSave->overwrite(false); 2267 2268 // Set original bookmarks uuid 2269 toSave->setBookmarkID(uuid); 2270 } 2271 } 2272 2273 void SKGMainPanel::overwriteBookmarkState() 2274 { 2275 SKGTRACEINFUNC(1) 2276 SKGError err; 2277 SKGTabPage* toSave = currentPage(); 2278 if (toSave != nullptr) { 2279 // Get bookmarks uuid 2280 QString uuid = toSave->getBookmarkID(); 2281 if (!uuid.isEmpty()) { 2282 // Overwrite 2283 toSave->overwrite(false); 2284 } 2285 } 2286 } 2287 2288 void SKGMainPanel::resetDefaultState() 2289 { 2290 SKGTRACEINFUNC(1) 2291 SKGError err; 2292 SKGTabPage* toSave = currentPage(); 2293 if (toSave != nullptr) { 2294 QString name = toSave->getDefaultStateAttribute(); 2295 if (!name.isEmpty()) { 2296 SKGBEGINLIGHTTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Reset default state"), err) 2297 IFOKDO(err, getDocument()->setParameter(name, QStringLiteral("<!DOCTYPE SKGML>"))) 2298 2299 // Refresh panel 2300 IFOK(err) toSave->setState(QLatin1String("")); 2301 } 2302 } 2303 2304 // status bar 2305 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Default state has been reset"))) 2306 displayErrorMessage(err); 2307 } 2308 2309 void SKGMainPanel::addTab() 2310 { 2311 SKGTRACEINFUNC(1) 2312 SKGTabPage* cPage = currentPage(); 2313 if (cPage != nullptr) { 2314 openPage(getPluginByName(cPage->objectName())); 2315 } 2316 } 2317 2318 bool SKGMainPanel::eventFilter(QObject* iObject, QEvent* iEvent) 2319 { 2320 if ((iObject != nullptr) && (iEvent != nullptr) && iEvent->type() == QEvent::Resize) { 2321 auto* rEvent = dynamic_cast<QResizeEvent*>(iEvent); 2322 if (rEvent != nullptr) { 2323 QSize newSize = rEvent->size(); 2324 2325 // Compute icon size 2326 int s = qMax(qMin(newSize.width() / 5, 64), 16); 2327 d->ui.kContextList->setIconSize(QSize(s, s)); 2328 } 2329 } 2330 return KXmlGuiWindow::eventFilter(iObject, iEvent); 2331 } 2332 2333 QStringList SKGMainPanel::getTipsOfDay() const 2334 { 2335 return d->m_tipsOfTheDay; 2336 } 2337 2338 QString SKGMainPanel::getTipOfDay() const 2339 { 2340 auto tips = getTipsOfDay(); 2341 return SKGServices::htmlToString(tips.at(QRandomGenerator::global()->bounded(tips.size()))); 2342 } 2343 2344 void SKGMainPanel::notify(int iTransaction) 2345 { 2346 SKGTRACEINFUNC(1) 2347 SKGTRACEL(1) << "iTransaction=" << iTransaction << SKGENDL; 2348 2349 // Notify 2350 SKGObjectBase transaction(getDocument(), QStringLiteral("doctransaction"), iTransaction); 2351 if (iTransaction == 0 || transaction.getAttribute(QStringLiteral("t_mode")) != QStringLiteral("R")) { 2352 SKGDocument::SKGMessageList msg; 2353 getDocument()->getMessages(iTransaction, msg, false); 2354 int nbMessages = msg.count(); 2355 if (nbMessages != 0) { 2356 // Build list of types 2357 SKGDocument::MessageType maxType = SKGDocument::Positive; 2358 QList<SKGDocument::MessageType> listGroups; 2359 listGroups.reserve(nbMessages); 2360 for (int i = 0; i < nbMessages; ++i) { 2361 SKGDocument::SKGMessage m = msg.at(i); 2362 // if the message has an action, it can not be grouped 2363 if (!m.Action.isEmpty()) { 2364 displayMessage(m.Text, m.Type, m.Action); 2365 msg.removeAt(i); 2366 i--; 2367 nbMessages--; 2368 } else { 2369 if (listGroups.isEmpty() || m.Type != listGroups.at(listGroups.count() - 1)) { 2370 listGroups.push_back(m.Type); 2371 } 2372 if (static_cast<int>(m.Type) >= static_cast<int>(maxType)) { 2373 maxType = m.Type; 2374 } 2375 } 2376 } 2377 2378 // Is the number of type acceptable? 2379 bool modeGrouped = false; 2380 if (listGroups.count() > 5 || nbMessages > 20) { 2381 // Too many group ==> simplification 2382 listGroups.clear(); 2383 listGroups.push_back(maxType); 2384 modeGrouped = true; 2385 } 2386 2387 // Build message 2388 if (nbMessages != 0) { 2389 QString message; 2390 int indexGroup = 0; 2391 for (int i = 0; i < nbMessages; ++i) { 2392 auto m = msg.at(i); 2393 auto t = m.Type; 2394 if (modeGrouped) { 2395 if (t == SKGDocument::Warning) { 2396 m.Text = i18nc("Warning header", "Warning: %1", m.Text); 2397 } else if (t == SKGDocument::Error) { 2398 m.Text = i18nc("Error header", "Error: %1", m.Text); 2399 } else if (t == SKGDocument::Information) { 2400 m.Text = i18nc("Information header", "Information: %1", m.Text); 2401 } else if (t == SKGDocument::Positive) { 2402 m.Text = i18nc("Done header", "Done: %1", m.Text); 2403 } 2404 } 2405 if (modeGrouped || t == listGroups.at(indexGroup)) { 2406 // Same group 2407 if (!message.isEmpty()) { 2408 message += QStringLiteral("<br>"); 2409 } 2410 message += m.Text; 2411 } else { 2412 // Different group 2413 displayMessage(message, listGroups.at(indexGroup)); 2414 2415 // Reset message 2416 message = m.Text; 2417 2418 indexGroup++; 2419 } 2420 } 2421 2422 if (nbMessages < 21 || !SKGServices::getEnvVariable(QStringLiteral("SKGTEST")).isEmpty()) { 2423 // Display a simple notification 2424 /*auto notify = new KNotification(KAboutData::applicationData().componentName() % "_info_event" , this); 2425 notify->setText(message); 2426 notify->sendEvent();*/ 2427 displayMessage(message, listGroups.at(indexGroup)); 2428 } else { 2429 // Too many message, display a warning panel 2430 KMessageBox::information(SKGMainPanel::getMainPanel(), message, i18nc("Noun", "Notification")); 2431 } 2432 } 2433 } 2434 } 2435 } 2436 2437 void SKGMainPanel::changeEvent(QEvent* e) 2438 { 2439 KXmlGuiWindow::changeEvent(e); 2440 } 2441 2442 QLabel* SKGMainPanel::statusNormalMessage() const 2443 { 2444 return d->m_kNormalMessage; 2445 } 2446 2447 KMessageWidget* SKGMainPanel::getMessageWidget(const QString& iMessage, SKGDocument::MessageType iType, const QString& iAction, bool iAutoKillOnClick) 2448 { 2449 KMessageWidget* msg = nullptr; 2450 if (!iMessage.isEmpty()) { 2451 msg = new KMessageWidget(this); 2452 msg->setText(iMessage); 2453 msg->setIcon(SKGServices::fromTheme(iType == SKGDocument::Positive ? QStringLiteral("dialog-positive") : 2454 iType == SKGDocument::Information ? QStringLiteral("dialog-information") : 2455 iType == SKGDocument::Warning ? QStringLiteral("dialog-warning") : QStringLiteral("dialog-error"))); 2456 msg->setMessageType(static_cast<KMessageWidget::MessageType>(iType)); 2457 if (!iAction.isEmpty()) { 2458 QUrl url(iAction); 2459 if (url.scheme() == QStringLiteral("skg")) { 2460 QAction* action = SKGMainPanel::getMainPanel()->getGlobalAction(url.host(), false); 2461 QAction* act = nullptr; 2462 if (action != nullptr) { 2463 // This is an action 2464 act = new QAction(action->icon(), action->text(), SKGMainPanel::getMainPanel()); 2465 } else { 2466 // This is a default action 2467 act = new QAction(SKGServices::fromTheme(QStringLiteral("open")), i18nc("Verb", "Open …"), SKGMainPanel::getMainPanel()); 2468 } 2469 2470 act->setData(iAction); 2471 2472 msg->addAction(act); 2473 connect(act, &QAction::triggered, this, [ = ] { openPage(QUrl(qobject_cast< QAction* >(sender())->data().toString()), true);}); 2474 if (iAutoKillOnClick) { 2475 connect(act, &QAction::triggered, msg, &KMessageWidget::deleteLater, Qt::QueuedConnection); 2476 } 2477 } 2478 } 2479 } 2480 return msg; 2481 } 2482 2483 KMessageWidget* SKGMainPanel::displayMessage(const QString& iMessage, SKGDocument::MessageType iType, const QString& iAction) 2484 { 2485 // Create message widget 2486 KMessageWidget* msg = nullptr; 2487 if (!iMessage.isEmpty()) { 2488 msg = getMessageWidget(iMessage, iType, iAction, true); 2489 QTimer::singleShot(iType == SKGDocument::Positive ? 5000 : iType == SKGDocument::Information ? 10000 : 20000, Qt::CoarseTimer, msg, &KMessageWidget::deleteLater); 2490 msg->show(); 2491 d->m_mainLayout->insertWidget(qMax(d->m_mainLayout->indexOf(d->m_mainWidget) - 1, 0), msg); 2492 2493 // Store message 2494 auto msg2 = getMessageWidget(iMessage, iType, iAction, false); 2495 auto* l = qobject_cast< QVBoxLayout* >(d->ui.kMessagesLayout->layout()); 2496 if (l != nullptr) { 2497 l->insertWidget(0, msg2); 2498 } 2499 } 2500 2501 // Emit message 2502 // [Event/error] 2503 // [Event/neutral] 2504 // [Event/positive] 2505 auto notification = new KNotification(iType == SKGDocument::Error ? QStringLiteral("error") : 2506 (iType == SKGDocument::Positive ? QStringLiteral("positive") : 2507 (iType == SKGDocument::Warning ? QStringLiteral("negative") : 2508 QStringLiteral("neutral")))); 2509 notification->setWidget(this); 2510 notification->setText(iMessage); 2511 notification->sendEvent(); 2512 2513 // Alert 2514 if (iType == SKGDocument::Error || iType == SKGDocument::Warning) { 2515 qApp->alert(this); 2516 } 2517 2518 return msg; 2519 } 2520 2521 KMessageWidget* SKGMainPanel::displayErrorMessage(const QString& iMessage) 2522 { 2523 QString msg = iMessage; 2524 if (msg.isEmpty()) { 2525 auto* act = qobject_cast< QAction* >(sender()); 2526 if (act != nullptr) { 2527 msg = act->data().toString(); 2528 } 2529 } 2530 return displayMessage(msg, SKGDocument::Error); 2531 } 2532 2533 KMessageWidget* SKGMainPanel::displayErrorMessage(const SKGError& iError, bool iNotifyIfNoError) 2534 { 2535 return displayErrorMessage(iError, nullptr, iNotifyIfNoError); 2536 } 2537 2538 KMessageWidget* SKGMainPanel::displayErrorMessage(const SKGError& iError, QAction* iAction, bool iNotifyIfNoError) 2539 { 2540 SKGTRACEINFUNC(1) 2541 KMessageWidget* msg = nullptr; 2542 SKGMainPanel* parent = SKGMainPanel::getMainPanel(); 2543 if (parent != nullptr) { 2544 if (iError) { 2545 // Get the message 2546 //BUG 423311: Remove history button 2547 msg = parent->displayMessage(iError.getFullMessageWithHistorical(), SKGDocument::Error, iError.getAction()); 2548 2549 // Add history action in case of 2550 /*if (iError.getHistoricalSize() != 0) { 2551 auto history = new QAction(i18nc("Noun", "History"), msg); 2552 history->setIcon(SKGServices::fromTheme(QStringLiteral("dialog-information"))); 2553 history->setData(iError.getFullMessageWithHistorical()); 2554 msg->addAction(history); 2555 connect(history, &QAction::triggered, parent, [ = ] { parent->displayErrorMessage();}); 2556 connect(history, &QAction::triggered, msg, &KMessageWidget::deleteLater, Qt::QueuedConnection); 2557 }*/ 2558 2559 // Add the additional action 2560 if (iAction != nullptr) { 2561 iAction->setParent(msg); 2562 msg->addAction(iAction); 2563 connect(iAction, &QAction::triggered, msg, &KMessageWidget::deleteLater, Qt::QueuedConnection); 2564 } 2565 } else { 2566 if (iNotifyIfNoError) { 2567 auto notification = new KNotification(QStringLiteral("positive")); 2568 notification->setWidget(parent); 2569 notification->setText(iError.getFullMessage()); 2570 notification->sendEvent(); 2571 } 2572 // Status bar 2573 QLabel* label = parent->statusNormalMessage(); 2574 QString message = iError.getMessage(); 2575 if ((label != nullptr) && !message.isEmpty()) { 2576 label->setText(message); 2577 } 2578 } 2579 } 2580 return msg; 2581 } 2582 2583 void SKGMainPanel::onCancelCurrentAction() 2584 { 2585 SKGMainPanelPrivate::m_currentActionCanceled = true; 2586 } 2587 2588 void SKGMainPanel::onQuitAction() 2589 { 2590 // Bug 2777697: To be sure that all page modifications are closed 2591 closeAllPages(true); 2592 // Bug 2777697: 2593 2594 qApp->closeAllWindows(); 2595 } 2596 2597 QString SKGMainPanel::getSaveFileName(const QString& iStartDir, const QString& iFilter, QWidget* iParent, QString* iCodec) 2598 { 2599 QString fileName; 2600 2601 QString lastCodecUsed = QTextCodec::codecForLocale()->name(); 2602 KEncodingFileDialog::Result result = KEncodingFileDialog::getSaveUrlAndEncoding(lastCodecUsed, QUrl::fromLocalFile(QUrl(iStartDir).toLocalFile()), iFilter, iParent); 2603 if (!result.URLs.isEmpty()) { 2604 fileName = result.URLs.at(0).toLocalFile(); 2605 } 2606 if (iCodec != nullptr) { 2607 *iCodec = result.encoding; 2608 } 2609 if (fileName.isEmpty()) { 2610 return QLatin1String(""); 2611 } 2612 QFile f(fileName); 2613 if (f.exists() && KMessageBox::warningContinueCancel(iParent, 2614 i18nc("Question", "File <b>%1</b> already exists. Do you really want to overwrite it?", fileName), 2615 i18nc("Question", "Warning"), 2616 KGuiItem(i18nc("Verb", "Save"), SKGServices::fromTheme(QStringLiteral("document-save")))) != KMessageBox::Continue) { 2617 return QLatin1String(""); 2618 } 2619 2620 return fileName; 2621 } 2622 2623 void SKGMainPanel::fillWithDistinctValue( 2624 const QList<QWidget*>& iWidgets, 2625 SKGDocument* iDoc, 2626 const QString& iTable, 2627 const QString& iAttribut, 2628 const QString& iWhereClause, 2629 bool iAddoperators) 2630 { 2631 SKGTRACEINFUNC(10) 2632 2633 if (iDoc != nullptr) { 2634 { 2635 // Get list 2636 QStringList list; 2637 { 2638 SKGTRACEIN(10, "SKGMainPanel::fillWithDistinctValue-build list " % iTable % " " % iAttribut) 2639 iDoc->getDistinctValues(iTable, iAttribut, iWhereClause, list); 2640 if (!list.isEmpty() && !list.at(0).isEmpty()) { 2641 list.insert(0, QLatin1String("")); 2642 } 2643 2644 // Sorting list 2645 { 2646 SKGTRACEIN(10, "SKGMainPanel::fillWithDistinctValue-build list sorting " % iTable % " " % iAttribut) 2647 // Correction bug 202341 vvv 2648 QCollator c; 2649 std::sort(list.begin(), list.end(), [&](const QString & a, const QString & b) { 2650 return c.compare(a, b) < 0; 2651 }); 2652 } 2653 2654 // Add operator 2655 if (iAddoperators) { 2656 list.push_back('=' % i18nc("Key word to modify a string into a field", "capitalize")); 2657 list.push_back('=' % i18nc("Key word to modify a string into a field", "capwords")); 2658 list.push_back('=' % i18nc("Key word to modify a string into a field", "lower")); 2659 list.push_back('=' % i18nc("Key word to modify a string into a field", "trim")); 2660 list.push_back('=' % i18nc("Key word to modify a string into a field", "upper")); 2661 } 2662 } 2663 2664 { 2665 SKGTRACEIN(10, "SKGMainPanel::fillWithDistinctValue-fill " % iTable % " " % iAttribut) 2666 SKGTRACEL(10) << "list.count()=" << list.count() << SKGENDL; 2667 for (auto w : qAsConst(iWidgets)) { 2668 auto comp = new QCompleter(list, w); 2669 if (comp != nullptr) { 2670 comp->setCaseSensitivity(Qt::CaseInsensitive); 2671 comp->setFilterMode(Qt::MatchContains); 2672 2673 // Fill completion 2674 auto* kcmb = qobject_cast<KComboBox*> (w); 2675 if (kcmb != nullptr) { 2676 // Fill combo 2677 kcmb->clear(); 2678 kcmb->addItems(list); 2679 2680 if (kcmb->isEditable()) { 2681 kcmb->setCompleter(comp); 2682 } 2683 } else { 2684 auto* kline = qobject_cast<QLineEdit*> (w); 2685 if (kline != nullptr) { 2686 kline->setClearButtonEnabled(true); 2687 kline->setCompleter(comp); 2688 } 2689 } 2690 } 2691 } 2692 } 2693 } 2694 } 2695 } 2696 2697 SKGMainPanel* SKGMainPanel::getMainPanel() 2698 { 2699 return SKGMainPanelPrivate::m_mainPanel; 2700 } 2701 2702 void SKGMainPanel::onZoomChanged() 2703 { 2704 SKGTabPage* toSave = currentPage(); 2705 if (toSave != nullptr) { 2706 toSave->setZoomPosition(d->m_zoomSelector->value()); 2707 d->m_zoomSelector->setValue(toSave->zoomPosition()); // In case of a limit is reached 2708 } 2709 } 2710 2711 void SKGMainPanel::setMainWidget(QWidget* iWidget) 2712 { 2713 if (d->m_mainWidget == nullptr && d->m_mainLayout != nullptr && iWidget != nullptr) { 2714 d->m_mainWidget = iWidget; 2715 d->m_mainLayout->addWidget(d->m_mainWidget); 2716 2717 // Show/hide main widget 2718 d->m_tabWidget->setVisible(d->m_tabWidget->count() != 0); 2719 if (d->m_mainWidget != nullptr) { 2720 d->m_mainWidget->setVisible(!d->m_tabWidget->isVisible()); 2721 } 2722 } 2723 } 2724 2725 SKGTabWidget* SKGMainPanel::getTabWidget() const 2726 { 2727 return d->m_tabWidget; 2728 } 2729 2730 void SKGMainPanel::onClearMessages() 2731 { 2732 QLayout* l = d->ui.kMessagesLayout->layout(); 2733 if (l != nullptr) { 2734 // Remove all item of the layout 2735 while (l->count() > 1) { 2736 QLayoutItem* child = l->takeAt(0); 2737 if (child != nullptr) { 2738 QWidget* w = child->widget(); 2739 delete w; 2740 delete child; 2741 } 2742 } 2743 } 2744 } 2745 2746 void SKGMainPanel::onMigrateToSQLCipher() 2747 { 2748 SKGError err; 2749 SKGTRACEINFUNCRC(10, err) 2750 if (getDocument()->isFileModified()) { 2751 err = SKGError(ERR_ABORT, i18nc("An information message", "The document must be saved to be migrated."), QStringLiteral("skg://file_save")); 2752 } else { 2753 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 2754 2755 // Set parameters 2756 QString input = getDocument()->getCurrentFileName(); 2757 QString tmp = input % ".sqlcipher"; 2758 QString output = input % "_migrated.skg"; 2759 output = output.replace(QStringLiteral(".skg_migrated"), QStringLiteral("_migrated")); 2760 2761 // Build argument 2762 QStringList arg; 2763 arg.push_back(QStringLiteral("--in")); 2764 arg.push_back(input); 2765 arg.push_back(QStringLiteral("--out")); 2766 arg.push_back(tmp); 2767 2768 2769 QString password = getDocument()->getPassword(); 2770 if (!password.isEmpty()) { 2771 arg.push_back(QStringLiteral("--param")); 2772 arg.push_back(QStringLiteral("password")); 2773 arg.push_back(QStringLiteral("--value")); 2774 arg.push_back(password); 2775 password = " --param password --value \"" % password % "\""; 2776 } 2777 2778 // Conversion skg => sqlcipher 2779 QString cmd = "skroogeconvert --in \"" % input % "\" --out \"" % tmp % "\"" % password; 2780 int rc = QProcess::execute(QStringLiteral("skroogeconvert"), arg); 2781 if (rc != 0) { 2782 err.setReturnCode(ERR_FAIL).setMessage(i18nc("Error message", "The following command line failed with code %2:\n'%1'", cmd, rc)); 2783 } else { 2784 cmd = "skroogeconvert --in \"" % tmp % "\" --out \"" % output % "\"" % password; 2785 arg[1] = tmp; 2786 arg[3] = output; 2787 rc = QProcess::execute(QStringLiteral("skroogeconvert"), arg); 2788 if (rc != 0) { 2789 err.setReturnCode(ERR_FAIL).setMessage(i18nc("Error message", "The following command line failed with code %2:\n'%1'", cmd, rc)); 2790 } else { 2791 getDocument()->sendMessage(i18nc("Positive message", "You document has been migrated.\nHere is the new file:\n%1", output), SKGDocument::Positive, "skg://file_open/?filename=" % output); 2792 notify(); 2793 } 2794 } 2795 QFile(tmp).remove(); 2796 2797 QApplication::restoreOverrideCursor(); 2798 } 2799 2800 // Display error 2801 SKGMainPanel::displayErrorMessage(err); 2802 } 2803 2804 QString SKGMainPanel::dateToString(QDate iDate) 2805 { 2806 switch (skgbasegui_settings::date_format()) { 2807 case 0: 2808 return QLocale().toString(iDate, QLocale::ShortFormat); 2809 case 1: 2810 return QLocale().toString(iDate, QLocale::LongFormat); 2811 case 3: 2812 return KFormat().formatRelativeDate(iDate, QLocale::LongFormat); 2813 case 4: 2814 return iDate.toString(Qt::ISODate); 2815 case 2: 2816 default: 2817 return KFormat().formatRelativeDate(iDate, QLocale::ShortFormat); 2818 } 2819 }