File indexing completed on 2025-02-02 04:56:52
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 is a plugin for bookmarks management. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgbookmarkplugin.h" 0012 0013 #include <qwidget.h> 0014 0015 #include <kaboutdata.h> 0016 #include <kactioncollection.h> 0017 #include <kpluginfactory.h> 0018 #include <ktoolbarpopupaction.h> 0019 0020 #include "skgbookmark_settings.h" 0021 #include "skgbookmarkplugindockwidget.h" 0022 #include "skgerror.h" 0023 #include "skgmainpanel.h" 0024 #include "skgnodeobject.h" 0025 #include "skgservices.h" 0026 #include "skgtraces.h" 0027 #include "skgtransactionmng.h" 0028 0029 /** 0030 * This plugin factory. 0031 */ 0032 K_PLUGIN_CLASS_WITH_JSON(SKGBookmarkPlugin, "metadata.json") 0033 0034 SKGBookmarkPlugin::SKGBookmarkPlugin(QWidget* iWidget, QObject* iParent, const QVariantList& iArg) : 0035 SKGInterfacePlugin(iParent), m_currentDocument(nullptr), m_dockWidget(nullptr), m_bookmarkMenu(nullptr) 0036 { 0037 Q_UNUSED(iArg) 0038 Q_UNUSED(iWidget) 0039 SKGTRACEINFUNC(10) 0040 } 0041 0042 SKGBookmarkPlugin::~SKGBookmarkPlugin() 0043 { 0044 SKGTRACEINFUNC(10) 0045 m_currentDocument = nullptr; 0046 m_dockWidget = nullptr; 0047 m_bookmarkMenu = nullptr; 0048 } 0049 0050 bool SKGBookmarkPlugin::setupActions(SKGDocument* iDocument) 0051 { 0052 SKGTRACEINFUNC(10) 0053 0054 m_currentDocument = iDocument; 0055 0056 setComponentName(QStringLiteral("skg_bookmark"), title()); 0057 setXMLFile(QStringLiteral("skg_bookmark.rc")); 0058 0059 m_dockWidget = new QDockWidget(SKGMainPanel::getMainPanel()); 0060 m_dockWidget->setObjectName(QStringLiteral("skg_bookmark_docwidget")); 0061 m_dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); 0062 m_dockWidget->setWindowTitle(title()); 0063 m_dockWidget->setWidget(new SKGBookmarkPluginDockWidget(m_dockWidget, m_currentDocument)); 0064 0065 // add action to control hide / display of Bookmarks 0066 QAction* toggle = m_dockWidget->toggleViewAction(); 0067 QAction* panelAction = actionCollection()->addAction(QStringLiteral("view_bookmarks")); 0068 registerGlobalAction(QStringLiteral("view_bookmarks"), panelAction); 0069 panelAction->setCheckable(true); 0070 panelAction->setChecked(toggle->isChecked()); 0071 panelAction->setText(toggle->text()); 0072 actionCollection()->setDefaultShortcut(panelAction, Qt::SHIFT + Qt::Key_F10); 0073 connect(panelAction, &QAction::triggered, toggle, &QAction::trigger); 0074 connect(toggle, &QAction::toggled, panelAction, &QAction::setChecked); 0075 0076 // Import bookmarks 0077 QStringList overlaybookmarks; 0078 overlaybookmarks.push_back(icon()); 0079 0080 auto actImportStdBookmark = new QAction(SKGServices::fromTheme(QStringLiteral("document-import"), overlaybookmarks), i18nc("Verb", "Import standard bookmarks"), this); 0081 connect(actImportStdBookmark, &QAction::triggered, this, &SKGBookmarkPlugin::importStandardBookmarks); 0082 registerGlobalAction(QStringLiteral("import_standard_bookmarks"), actImportStdBookmark); 0083 0084 // 0085 QAction* goHomeAction = KStandardAction::home(this, SLOT(goHome()), actionCollection()); 0086 goHomeAction->setPriority(QAction::LowPriority); 0087 registerGlobalAction(QStringLiteral("go_home"), goHomeAction); 0088 0089 // Bookmark 0090 auto actBookmark = new KToolBarPopupAction(SKGServices::fromTheme(QStringLiteral("bookmark-new-list")), i18nc("Verb, action to display bookmarks", "Bookmarks"), this); 0091 connect(actBookmark, &KToolBarPopupAction::triggered, this, &SKGBookmarkPlugin::onOpenBookmark); 0092 m_bookmarkMenu = actBookmark->menu(); 0093 if (m_bookmarkMenu != nullptr) { 0094 m_bookmarkMenu->setProperty("id", 0); 0095 connect(m_bookmarkMenu, &QMenu::aboutToShow, this, &SKGBookmarkPlugin::onShowBookmarkMenu); 0096 } 0097 0098 actBookmark->setStickyMenu(false); 0099 actBookmark->setDelayed(false); 0100 actBookmark->setData(0); 0101 actBookmark->setPriority(QAction::LowPriority); 0102 0103 registerGlobalAction(QStringLiteral("edit_bookmark"), actBookmark); 0104 0105 return true; 0106 } 0107 0108 QWidget* SKGBookmarkPlugin::getPreferenceWidget() 0109 { 0110 SKGTRACEINFUNC(10) 0111 auto w = new QWidget(); 0112 ui.setupUi(w); 0113 return w; 0114 } 0115 0116 KConfigSkeleton* SKGBookmarkPlugin::getPreferenceSkeleton() 0117 { 0118 return skgbookmark_settings::self(); 0119 } 0120 0121 void SKGBookmarkPlugin::refresh() 0122 { 0123 SKGTRACEINFUNC(10) 0124 if (m_dockWidget != nullptr) { 0125 auto* p = qobject_cast<SKGBookmarkPluginDockWidget*>(m_dockWidget->widget()); 0126 if (p != nullptr) { 0127 p->refresh(); 0128 } 0129 } 0130 0131 if (m_currentDocument != nullptr) { 0132 // Automatic bookmarks creation 0133 if (m_currentDocument->getMainDatabase() != nullptr) { 0134 QString doc_id = m_currentDocument->getUniqueIdentifier(); 0135 if (m_docUniqueIdentifier != doc_id) { 0136 m_docUniqueIdentifier = doc_id; 0137 0138 bool exist = false; 0139 SKGError err = m_currentDocument->existObjects(QStringLiteral("node"), QLatin1String(""), exist); 0140 if (!err && !exist) { 0141 importStandardBookmarks(); 0142 0143 // The file is considered has not modified 0144 m_currentDocument->setFileNotModified(); 0145 } 0146 0147 // Automatic open of autostart bookmark 0148 if (!err && !(QApplication::keyboardModifiers() &Qt::ShiftModifier)) { 0149 goHome(); 0150 } 0151 } 0152 } 0153 } 0154 } 0155 0156 QString SKGBookmarkPlugin::title() const 0157 { 0158 return i18nc("Noun, a bookmark as in a webbrowser bookmark", "Bookmarks"); 0159 } 0160 0161 QString SKGBookmarkPlugin::icon() const 0162 { 0163 return QStringLiteral("bookmarks"); 0164 } 0165 0166 QStringList SKGBookmarkPlugin::tips() const 0167 { 0168 QStringList output; 0169 output.push_back(i18nc("Description of a tips", "<p>… some bookmarks can be opened automatically when the application is launched.</p>")); 0170 output.push_back(i18nc("Description of a tips", "<p>… bookmarks can be reorganized by drag & drop.</p>")); 0171 output.push_back(i18nc("Description of a tips", "<p>… a double click on a folder of bookmarks will open all the bookmarks it contains.</p>")); 0172 output.push_back(i18nc("Description of a tips", "<p>… you can <a href=\"skg://import_standard_bookmarks\">import standard bookmarks</a>.</p>")); 0173 return output; 0174 } 0175 0176 int SKGBookmarkPlugin::getOrder() const 0177 { 0178 return 3; 0179 } 0180 0181 QDockWidget* SKGBookmarkPlugin::getDockWidget() 0182 { 0183 return m_dockWidget; 0184 } 0185 0186 void SKGBookmarkPlugin::importStandardBookmarks() 0187 { 0188 SKGTRACEINFUNC(10) 0189 SKGError err; 0190 SKGBEGINTRANSACTION(*m_currentDocument, i18nc("Noun, name of the user action", "Import standard bookmarks"), err) 0191 0192 QStringList bks; 0193 bks << i18nc("Noun, bookmark name", "Dashboard") % "|N|dashboard-show|\"Dashboard plugin\";\"Dashboard\";\"<!DOCTYPE SKGML><parameters zoomPosition=\"\"0\"\"> <ITEM-1 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge bank plugin\"\" state=\"\"<!DOCTYPE SKGML>
<parameters menuOther="Y" menuCurrent="Y" menuFavorite="N" menuAssets="Y" menuInvestment="Y" menuCreditCard="Y"/>
\"\"/> <ITEM-2 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge operation plugin\"\" state=\"\"<!DOCTYPE SKGML>" 0194 "
<parameters menuTransfert="Y"/>
\"\"/> <ITEM-3 zoom=\"\"0\"\" index=\"\"1\"\" name=\"\"Skrooge operation plugin\"\" state=\"\"\"\"/> <ITEM-4 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge scheduled plugin\"\" state=\"\"\"\"/> <ITEM-5 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge search plugin\"\" state=\"\"<!DOCTYPE SKGML>" 0195 "
<parameters menuFavorite="N"/>
\"\"/> <ITEM-6 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge unit plugin\"\" state=\"\"<!DOCTYPE SKGML>
<parameters menuShares="Y" menuSharesOwnedOnly="N" menuIndexes="Y"/>
\"\"/> <ITEM-7 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge calculator plugin\"\" state=\"\"\"\"/></parameters>\"" 0196 << i18nc("Noun, bookmark name", "Report > Income vs Expenditure on 12 last months") % "|N|view-statistics|\"Skrooge report plugin\";\"Rapport\";\"<!DOCTYPE SKGML><parameters expenses=\"\"Y\"\" tableAndGraphState=\"\"<!DOCTYPE SKGML>" 0197 "
<parameters graphMode="1" graphicViewState="&lt;!DOCTYPE SKGML>&#xa;&lt;parameters isToolBarVisible=&quot;Y&quot; antialiasing=&quot;Y&quot;/>&#xa;" splitterState="000000ff00000000000000020000025b0000032901000000060100000001" bottomToolBarVisible="Y" filter="" legendVisible="N" allPositive="Y" linearRegressionVisible="Y" sortColumn="0" limitVisible="Y" web="&lt;!DOCTYPE SKGML>" 0198 "&#xa;&lt;parameters zoomFactor=&quot;0&quot;/>&#xa;" sortOrder="0"/>
\"\" mode=\"\"0\"\" period=\"\"3\"\" incomes=\"\"Y\"\" interval=\"\"2\"\" lines=\"\"t_TYPEEXPENSENLS\"\" lines2=\"\"#NOTHING#\"\" nbLevelLines=\"\"0\"\" nbLevelColumns=\"\"0\"\" forecast=\"\"0\"\" columns=\"\"d_DATEMONTH\"\" nb_intervals=\"\"12\"\" forecastValue=\"\"20\"\" transfers=\"\"N\"\" currentPage=\"\"0\"\"/>\"" 0199 << i18nc("Noun, bookmark name", "Report > Pie categories in 12 last months") % "|N|view-statistics|\"Skrooge report plugin\";\"Rapport\";\"<!DOCTYPE SKGML><parameters expenses=\"\"Y\"\" tableAndGraphState=\"\"<!DOCTYPE SKGML>
<parameters graphMode="2" graphicViewState="&lt;!DOCTYPE SKGML>" 0200 "&#xa;&lt;parameters isToolBarVisible=&quot;Y&quot; antialiasing=&quot;Y&quot;/>&#xa;" splitterState="000000ff00000000000000020000025b0000032901000000060100000001" bottomToolBarVisible="Y" filter="" legendVisible="N" allPositive="Y" linearRegressionVisible="Y" sortColumn="-1" limitVisible="Y" web="&lt;!DOCTYPE SKGML>" 0201 "&#xa;&lt;parameters zoomFactor=&quot;0&quot;/>&#xa;" sortOrder="0"/>
\"\" mode=\"\"0\"\" period=\"\"3\"\" incomes=\"\"Y\"\" interval=\"\"2\"\" lines=\"\"t_REALCATEGORY\"\" lines2=\"\"#NOTHING#\"\" nbLevelLines=\"\"0\"\" nbLevelColumns=\"\"0\"\" forecast=\"\"0\"\" columns=\"\"d_DATEMONTH\"\" nb_intervals=\"\"12\"\" forecastValue=\"\"20\"\" transfers=\"\"N\"\" currentPage=\"\"0\"\"/>\"" 0202 << i18nc("Noun, bookmark name", "Report > History") % "|N|view-statistics|\"Skrooge report plugin\";\"Rapport\";\"<!DOCTYPE SKGML><parameters expenses=\"\"Y\"\" tableAndGraphState=\"\"<!DOCTYPE SKGML>" 0203 "
<parameters graphMode="1" graphicViewState="&lt;!DOCTYPE SKGML>&#xa;&lt;parameters isToolBarVisible=&quot;Y&quot; antialiasing=&quot;Y&quot;/>&#xa;" splitterState="000000ff0000000000000002000002b50000032601000000060100000001" bottomToolBarVisible="Y" filter="" legendVisible="N" allPositive="N" linearRegressionVisible="Y" sortColumn="-1" limitVisible="Y" web="&lt;!DOCTYPE SKGML>" 0204 "&#xa;&lt;parameters zoomFactor=&quot;0&quot;/>&#xa;" sortOrder="0"/>
\"\" mode=\"\"1\"\" period=\"\"0\"\" incomes=\"\"Y\"\" interval=\"\"2\"\" lines=\"\"#NOTHING#\"\" lines2=\"\"#NOTHING#\"\" nbLevelLines=\"\"0\"\" nbLevelColumns=\"\"0\"\" forecast=\"\"0\"\" columns=\"\"d_DATEMONTH\"\" nb_intervals=\"\"1\"\" forecastValue=\"\"20\"\" transfers=\"\"Y\"\" currentPage=\"\"0\"\"/>\""; 0205 0206 0207 for (const auto& bk : qAsConst(bks)) { 0208 QStringList line = SKGServices::splitCSVLine(bk, '|', false); 0209 if (line.count() == 4) { 0210 SKGNodeObject node; 0211 err = SKGNodeObject::createPathNode(m_currentDocument, line.at(0), node); 0212 IFOKDO(err, node.setAutoStart(line.at(1) == QStringLiteral("Y"))) 0213 IFOKDO(err, node.setIcon(line.at(2))) 0214 IFOKDO(err, node.setData(line.at(3))) 0215 IFOKDO(err, node.save()) 0216 } 0217 } 0218 0219 // status 0220 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Standard bookmarks imported."))) 0221 else { 0222 err.addError(ERR_FAIL, i18nc("Error message", "Import standard bookmarks failed")); 0223 } 0224 0225 // Display error 0226 SKGMainPanel::displayErrorMessage(err); 0227 } 0228 0229 void SKGBookmarkPlugin::goHome() 0230 { 0231 if (SKGMainPanel::getMainPanel() != nullptr) { 0232 SKGMainPanel::getMainPanel()->closeAllPages(false); // Home do not close pinned pages 0233 } 0234 0235 SKGObjectBase::SKGListSKGObjectBase oNodeList; 0236 if (m_currentDocument != nullptr) { 0237 m_currentDocument->getObjects(QStringLiteral("v_node"), QStringLiteral("t_autostart='Y' ORDER BY f_sortorder, t_name"), oNodeList); 0238 } 0239 int nbAutoStartedBookmarks = oNodeList.count(); 0240 for (int i = 0; i < nbAutoStartedBookmarks; ++i) { 0241 SKGNodeObject autostarted_bookmark(oNodeList.at(i)); 0242 autostarted_bookmark.load(); 0243 SKGTRACEIN(10, "autostarting bookmark : " % autostarted_bookmark.getName()) 0244 SKGBookmarkPluginDockWidget::openBookmark(autostarted_bookmark, i > 0, true); 0245 } 0246 } 0247 0248 void SKGBookmarkPlugin::onOpenBookmark() 0249 { 0250 auto* callerAction = qobject_cast<QAction*>(this->sender()); 0251 if (callerAction != nullptr) { 0252 SKGNodeObject node(m_currentDocument, callerAction->data().toInt()); 0253 SKGBookmarkPluginDockWidget::openBookmark(node, (QGuiApplication::mouseButtons() & Qt::MidButton) != 0u || (QApplication::keyboardModifiers() & Qt::ControlModifier) != 0u); 0254 } 0255 } 0256 0257 void SKGBookmarkPlugin::onAddBookmark() 0258 { 0259 SKGTRACEINFUNC(1) 0260 SKGError err; 0261 0262 // Get current page 0263 SKGNodeObject node; 0264 { 0265 // Get current selection 0266 SKGNodeObject parentNode; 0267 auto* callerAction = qobject_cast<QAction*>(this->sender()); 0268 if (callerAction != nullptr) { 0269 parentNode = SKGNodeObject(m_currentDocument, callerAction->data().toInt()); 0270 } 0271 0272 // Create bookmark 0273 err = SKGBookmarkPluginDockWidget::createNodeFromPage(SKGMainPanel::getMainPanel()->currentPage(), parentNode, node); 0274 } 0275 // status bar 0276 IFOK(err) { 0277 err = SKGError(0, i18nc("Successful message after an user action", "Bookmark created")); 0278 } 0279 SKGMainPanel::displayErrorMessage(err); 0280 } 0281 0282 void SKGBookmarkPlugin::onShowBookmarkMenu() 0283 { 0284 auto* callerMenu = qobject_cast<QMenu*>(this->sender()); 0285 if ((callerMenu != nullptr) && (m_currentDocument != nullptr)) { 0286 // Remove previous menu 0287 callerMenu->clear(); 0288 0289 // Build query 0290 QString wc = QStringLiteral("rd_node_id=0 OR rd_node_id IS NULL OR rd_node_id=''"); 0291 int idParent = callerMenu->property("id").toInt(); 0292 if (idParent != 0) { 0293 wc = "rd_node_id=" % SKGServices::intToString(idParent); 0294 } 0295 0296 // Build new menu 0297 SKGObjectBase::SKGListSKGObjectBase listNode; 0298 m_currentDocument->getObjects(QStringLiteral("v_node"), wc % " ORDER BY f_sortorder, t_name", listNode); 0299 int nb = listNode.count(); 0300 for (int i = 0; i < nb; ++i) { 0301 SKGNodeObject node(listNode.at(i)); 0302 if (node.isFolder()) { 0303 // This is a folder 0304 auto menu = new QMenu(callerMenu); 0305 if (menu != nullptr) { 0306 callerMenu->addMenu(menu); 0307 menu->setTitle(node.getName()); 0308 menu->setIcon(node.getIcon()); 0309 menu->setProperty("id", node.getID()); 0310 connect(menu, &QMenu::aboutToShow, this, &SKGBookmarkPlugin::onShowBookmarkMenu); 0311 } 0312 } else { 0313 // This is a bookmark 0314 auto act = new QAction(callerMenu); 0315 if (act != nullptr) { 0316 callerMenu->addAction(act); 0317 act->setText(node.getName()); 0318 act->setIcon(node.getIcon()); 0319 act->setData(node.getID()); 0320 connect(act, &QAction::triggered, this, &SKGBookmarkPlugin::onOpenBookmark); 0321 } 0322 } 0323 } 0324 0325 // Add separator 0326 auto sep = new QAction(this); 0327 sep->setSeparator(true); 0328 callerMenu->addAction(sep); 0329 0330 // This common actions 0331 { 0332 // Open all 0333 auto act = new QAction(callerMenu); 0334 if (act != nullptr) { 0335 callerMenu->addAction(act); 0336 act->setText(i18nc("Action", "Open all")); 0337 act->setIcon(SKGServices::fromTheme(QStringLiteral("quickopen"))); 0338 act->setData(idParent); 0339 connect(act, &QAction::triggered, this, &SKGBookmarkPlugin::onOpenBookmark); 0340 } 0341 if (SKGMainPanel::getMainPanel()->currentPageIndex() >= 0) { 0342 // Bookmark current here 0343 auto act2 = new QAction(callerMenu); 0344 if (act2 != nullptr) { 0345 callerMenu->addAction(act2); 0346 act2->setText(i18nc("Action", "Bookmark current page here")); 0347 act2->setIcon(SKGServices::fromTheme(QStringLiteral("list-add"))); 0348 act2->setData(idParent); 0349 0350 connect(act2, &QAction::triggered, this, &SKGBookmarkPlugin::onAddBookmark); 0351 } 0352 } 0353 } 0354 } 0355 } 0356 0357 #include <skgbookmarkplugin.moc>