diff --git a/plugins/skrooge/skrooge_bank/skgaccountboardwidget.cpp b/plugins/skrooge/skrooge_bank/skgaccountboardwidget.cpp index f579d8885..ffcabc4f6 100644 --- a/plugins/skrooge/skrooge_bank/skgaccountboardwidget.cpp +++ b/plugins/skrooge/skrooge_bank/skgaccountboardwidget.cpp @@ -1,393 +1,393 @@ /*************************************************************************** * Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ /** @file * This file is Skrooge plugin for bank management. * * @author Stephane MANKOWSKI / Guillaume DE BURE */ #include "skgaccountboardwidget.h" #include #include #include #include "skgaccountobject.h" #include "skgdocumentbank.h" #include "skgmainpanel.h" #include "skgservices.h" #include "skgtraces.h" #include "skgunitobject.h" SKGAccountBoardWidget::SKGAccountBoardWidget(QWidget* iParent, SKGDocument* iDocument) : SKGBoardWidget(iParent, iDocument, i18nc("Title of a dashboard widget", "Accounts")), m_refreshNeeded(true) { SKGTRACEINFUNC(10) // Create menu setContextMenuPolicy(Qt::ActionsContextMenu); // menu m_menuFavorite = new QAction(SKGServices::fromTheme(QStringLiteral("bookmarks")), i18nc("Display only favorite accounts", "Highlighted only"), this); m_menuFavorite->setCheckable(true); m_menuFavorite->setChecked(false); connect(m_menuFavorite, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuFavorite); m_menuPastOperations = new QAction(i18nc("Noun, a type of account", "Only past operations"), this); m_menuPastOperations->setCheckable(true); m_menuPastOperations->setChecked(false); connect(m_menuPastOperations, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuPastOperations); { auto sep = new QAction(this); sep->setSeparator(true); addAction(sep); } m_menuCurrent = new QAction(i18nc("Noun, a type of account", "Current"), this); m_menuCurrent->setCheckable(true); m_menuCurrent->setChecked(true); connect(m_menuCurrent, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuCurrent); m_menuCreditCard = new QAction(i18nc("Noun, a type of account", "Credit card"), this); m_menuCreditCard->setCheckable(true); m_menuCreditCard->setChecked(true); connect(m_menuCreditCard, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuCreditCard); m_menuSaving = new QAction(i18nc("Noun, a type of account", "Saving"), this); m_menuSaving->setCheckable(true); m_menuSaving->setChecked(true); connect(m_menuSaving, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuSaving); m_menuInvestment = new QAction(i18nc("Noun, a type of account", "Investment"), this); m_menuInvestment->setCheckable(true); m_menuInvestment->setChecked(true); connect(m_menuInvestment, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuInvestment); m_menuAssets = new QAction(i18nc("Noun, a type of account", "Assets"), this); m_menuAssets->setCheckable(true); m_menuAssets->setChecked(true); connect(m_menuAssets, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuAssets); m_menuLoan = new QAction(i18nc("Noun, a type of account", "Loan"), this); m_menuLoan->setCheckable(true); m_menuLoan->setChecked(true); connect(m_menuLoan, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuLoan); m_menuPension = new QAction(i18nc("Noun, a type of account", "Pension"), this); m_menuPension->setCheckable(true); m_menuPension->setChecked(true); connect(m_menuPension, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuPension); m_menuWallet = new QAction(i18nc("Noun, a type of account", "Wallet"), this); m_menuWallet->setCheckable(true); m_menuWallet->setChecked(true); connect(m_menuWallet, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuWallet); m_menuOther = new QAction(i18nc("Noun, a type of account", "Other"), this); m_menuOther->setCheckable(true); m_menuOther->setChecked(true); connect(m_menuOther, &QAction::triggered, this, [ = ]() { this->dataModified(); }); addAction(m_menuOther); m_label = new QLabel(); setMainWidget(m_label); // Refresh connect(getDocument(), &SKGDocument::tableModified, this, &SKGAccountBoardWidget::dataModified, Qt::QueuedConnection); connect(SKGMainPanel::getMainPanel(), &SKGMainPanel::currentPageChanged, this, &SKGAccountBoardWidget::pageChanged, Qt::QueuedConnection); connect(m_label, &QLabel::linkActivated, this, [ = ](const QString & val) { SKGMainPanel::getMainPanel()->openPage(val); }); } SKGAccountBoardWidget::~SKGAccountBoardWidget() { SKGTRACEINFUNC(10) m_menuAssets = nullptr; m_menuCurrent = nullptr; m_menuCreditCard = nullptr; m_menuSaving = nullptr; m_menuInvestment = nullptr; m_menuWallet = nullptr; m_menuLoan = nullptr; m_menuPension = nullptr; m_menuOther = nullptr; m_menuFavorite = nullptr; m_menuPastOperations = nullptr; } QString SKGAccountBoardWidget::getState() { QDomDocument doc(QStringLiteral("SKGML")); doc.setContent(SKGBoardWidget::getState()); QDomElement root = doc.documentElement(); root.setAttribute(QStringLiteral("menuFavorite"), (m_menuFavorite != nullptr) && m_menuFavorite->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuAssets"), (m_menuAssets != nullptr) && m_menuAssets->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuCurrent"), (m_menuCurrent != nullptr) && m_menuCurrent->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuCreditCard"), (m_menuCreditCard != nullptr) && m_menuCreditCard->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuSaving"), (m_menuSaving != nullptr) && m_menuSaving->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuInvestment"), (m_menuInvestment != nullptr) && m_menuInvestment->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuWallet"), (m_menuWallet != nullptr) && m_menuWallet->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuLoan"), (m_menuLoan != nullptr) && m_menuLoan->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuPension"), (m_menuPension != nullptr) && m_menuPension->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuOther"), (m_menuOther != nullptr) && m_menuOther->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); root.setAttribute(QStringLiteral("menuPastOperations"), (m_menuPastOperations != nullptr) && m_menuPastOperations->isChecked() ? QStringLiteral("Y") : QStringLiteral("N")); return doc.toString(); } void SKGAccountBoardWidget::setState(const QString& iState) { SKGBoardWidget::setState(iState); QDomDocument doc(QStringLiteral("SKGML")); doc.setContent(iState); QDomElement root = doc.documentElement(); if (m_menuFavorite != nullptr) { m_menuFavorite->setChecked(root.attribute(QStringLiteral("menuFavorite")) == QStringLiteral("Y")); } if (m_menuAssets != nullptr) { m_menuAssets->setChecked(root.attribute(QStringLiteral("menuAssets")) != QStringLiteral("N")); } if (m_menuCurrent != nullptr) { m_menuCurrent->setChecked(root.attribute(QStringLiteral("menuCurrent")) != QStringLiteral("N")); } if (m_menuCreditCard != nullptr) { m_menuCreditCard->setChecked(root.attribute(QStringLiteral("menuCreditCard")) != QStringLiteral("N")); } if (m_menuSaving != nullptr) { m_menuSaving->setChecked(root.attribute(QStringLiteral("menuSaving")) != QStringLiteral("N")); } if (m_menuInvestment != nullptr) { m_menuInvestment->setChecked(root.attribute(QStringLiteral("menuInvestment")) != QStringLiteral("N")); } if (m_menuWallet != nullptr) { m_menuWallet->setChecked(root.attribute(QStringLiteral("menuWallet")) != QStringLiteral("N")); } if (m_menuLoan != nullptr) { m_menuLoan->setChecked(root.attribute(QStringLiteral("menuLoan")) != QStringLiteral("N")); } if (m_menuPension != nullptr) { m_menuPension->setChecked(root.attribute(QStringLiteral("menuPension")) != QStringLiteral("N")); } if (m_menuOther != nullptr) { m_menuOther->setChecked(root.attribute(QStringLiteral("menuOther")) != QStringLiteral("N")); } if (m_menuPastOperations != nullptr) { m_menuPastOperations->setChecked(root.attribute(QStringLiteral("menuPastOperations")) == QStringLiteral("Y")); } dataModified(QLatin1String(""), 0); } void SKGAccountBoardWidget::pageChanged() { if (m_refreshNeeded) { dataModified(QLatin1String(""), 0); } } void SKGAccountBoardWidget::dataModified(const QString& iTableName, int iIdTransaction) { Q_UNUSED(iIdTransaction) if (iTableName == QStringLiteral("v_account_display") || iTableName.isEmpty()) { SKGTRACEINFUNC(10) SKGTabPage* page = SKGTabPage::parentTabPage(this); if (page != nullptr && page != SKGMainPanel::getMainPanel()->currentPage()) { m_refreshNeeded = true; return; } m_refreshNeeded = false; auto* doc = qobject_cast(getDocument()); if (doc != nullptr) { SKGServices::SKGUnitInfo primary = doc->getPrimaryUnit(); bool exist = false; SKGError err = doc->existObjects(QStringLiteral("account"), QLatin1String(""), exist); IFOK(err) { QString html; if (!exist) { html = "" % i18nc("Message, do not translate URL", "First, you have to create at least one account
from \"Bank and Account\" page or import operations.", "skg://Skrooge_bank_plugin", "skg://import_operation") % ""; } else { // Build where clause QString wc; if ((m_menuAssets != nullptr) && m_menuAssets->isChecked()) { wc = QStringLiteral("t_type='A'"); } if ((m_menuCurrent != nullptr) && m_menuCurrent->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='C'"); } if ((m_menuCreditCard != nullptr) && m_menuCreditCard->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='D'"); } if ((m_menuSaving != nullptr) && m_menuSaving->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='S'"); } if ((m_menuInvestment != nullptr) && m_menuInvestment->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='I'"); } if ((m_menuWallet != nullptr) && m_menuWallet->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='W'"); } if ((m_menuOther != nullptr) && m_menuOther->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='O'"); } if ((m_menuLoan != nullptr) && m_menuLoan->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='L'"); } if ((m_menuPension != nullptr) && m_menuPension->isChecked()) { if (!wc.isEmpty()) { wc += QStringLiteral(" OR "); } wc += QStringLiteral("t_type='P'"); } if (wc.isEmpty()) { wc = QStringLiteral("1=0"); } else if ((m_menuFavorite != nullptr) && m_menuFavorite->isChecked()) { wc = "t_bookmarked='Y' AND (" % wc % ')'; } // Build display SKGStringListList listTmp; err = doc->executeSelectSqliteOrder( QStringLiteral("SELECT t_name, t_TYPENLS, t_UNIT, ") % ((m_menuPastOperations != nullptr) && m_menuPastOperations->isChecked() ? "f_TODAYAMOUNT" : "f_CURRENTAMOUNT") % ", t_close from v_account_display WHERE (" % wc % ") ORDER BY t_TYPENLS, t_name", listTmp); IFOK(err) { KColorScheme scheme(QPalette::Normal, KColorScheme::Window); auto color = scheme.foreground(KColorScheme::NormalText).color().name().right(6); html += QStringLiteral(""; double sumTypeV1 = 0; double sumV1 = 0; int nbAdded = 0; QString currentType; int nb = listTmp.count(); for (int i = 1; i < nb; ++i) { // Ignore header const QStringList& r = listTmp.at(i); const QString& name = r.at(0); const QString& type = r.at(1); const QString& unitAccountSymbol = r.at(2); double v1 = SKGServices::stringToDouble(r.at(3)); bool closed = (r.at(4) == QStringLiteral("Y")); if (type != currentType) { - if (!currentType.isEmpty() && nbAdded>0) { + if (!currentType.isEmpty() && nbAdded > 0) { html += "" ""; sumTypeV1 = 0; nbAdded = 0; } currentType = type; } if (!closed || qAbs(v1) > 0.1) { html += QString("" ""); ++nbAdded; } sumTypeV1 += v1; sumV1 += v1; } if (!currentType.isEmpty()) { html += "" "" ""; } html += "" "" ""; html += QStringLiteral("
" % SKGServices::stringToHtml(i18nc("the numerical total of a sum of values", "Total of %1", currentType)) % "" % doc->formatMoney(sumTypeV1, primary) % "
") % SKGServices::stringToHtml(name) % ""; if (!unitAccountSymbol.isEmpty() && primary.Symbol != unitAccountSymbol) { SKGUnitObject unitAccount(getDocument()); unitAccount.setSymbol(unitAccountSymbol); unitAccount.load(); double unitAccountValue = SKGServices::stringToDouble(unitAccount.getAttribute(QStringLiteral("f_CURRENTAMOUNT"))); SKGServices::SKGUnitInfo u2 = primary; u2.Symbol = unitAccountSymbol; u2.NbDecimal = unitAccount.getNumberDecimal(); html += doc->formatMoney(v1 / unitAccountValue, u2); html += '='; } html += doc->formatMoney(v1, primary); html += QStringLiteral("
" % SKGServices::stringToHtml(i18nc("the numerical total of a sum of values", "Total of %1", currentType)) % "" % doc->formatMoney(sumTypeV1, primary) % "
" % SKGServices::stringToHtml(i18nc("Noun, the numerical total of a sum of values", "Total")) % "" % doc->formatMoney(sumV1, primary) % "
"); } } m_label->setText(html); } } } } diff --git a/skgbankmodeler/skgreportbank.cpp b/skgbankmodeler/skgreportbank.cpp index 7e1dca711..2ce20339e 100644 --- a/skgbankmodeler/skgreportbank.cpp +++ b/skgbankmodeler/skgreportbank.cpp @@ -1,779 +1,779 @@ /*************************************************************************** * Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ /** @file * A skrooge plugin for monthly report. * * @author Stephane MANKOWSKI */ #include "skgreportbank.h" #include #include #include #include #include "skgaccountobject.h" #include "skgdocumentbank.h" #include "skgoperationobject.h" #include "skgrecurrentoperationobject.h" #include "skgruleobject.h" #include "skgtraces.h" #include "skgunitobject.h" SKGReportBank::SKGReportBank(SKGDocument* iDocument) : SKGReport(iDocument) { SKGTRACEINFUNC(1) connect(this, &SKGReportBank::changed, this, &SKGReportBank::changed2); } SKGReportBank::~SKGReportBank() { SKGTRACEINFUNC(1) } QVariantList SKGReportBank::getAlarms() { QString cacheId = QStringLiteral("getAlarms"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); if (doc != nullptr) { SKGServices::SKGUnitInfo primary = doc->getPrimaryUnit(); SKGObjectBase::SKGListSKGObjectBase rules; SKGError err = doc->getObjects(QStringLiteral("v_rule"), QStringLiteral("t_action_type='A' ORDER BY i_ORDER"), rules); int nb = rules.count(); if (nb != 0) { for (int i = 0; !err && i < nb; ++i) { SKGRuleObject rule(rules.at(i)); SKGRuleObject::SKGAlarmInfo alarm = rule.getAlarmInfo(); QVariantList item; // clazy:exclude=container-inside-loop // Build the message if (alarm.Message.contains(QLatin1String("%3"))) { alarm.Message = alarm.Message.arg(doc->formatMoney(alarm.Amount, primary, false), doc->formatMoney(alarm.Limit, primary, false), doc->formatMoney(alarm.Amount - alarm.Limit, primary, false)); } else if (alarm.Message.contains(QLatin1String("%2"))) { alarm.Message = alarm.Message.arg(doc->formatMoney(alarm.Amount, primary, false), doc->formatMoney(alarm.Limit, primary, false)); } else if (alarm.Message.contains(QLatin1String("%1"))) { alarm.Message = alarm.Message.arg(doc->formatMoney(alarm.Amount, primary, false)); } item.push_back(alarm.Message); item.push_back(alarm.Amount); item.push_back(alarm.Limit); item.push_back(alarm.Amount - alarm.Limit); item.push_back(alarm.Raised); table.push_back(item); } } m_cache[cacheId] = table; } } return table; } QVariantList SKGReportBank::getInterests() { QString cacheId = QStringLiteral("getInterests"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); if (doc != nullptr) { // Build display int year = SKGServices::periodToDate(getPeriod()).year(); SKGObjectBase::SKGListSKGObjectBase objs; SKGError err = doc->getObjects(QStringLiteral("v_account"), QStringLiteral("t_close='N' AND EXISTS(select 1 from interest where interest.rd_account_id=v_account.id) ORDER BY t_name"), objs); IFOK(err) { int nb = objs.count(); table.reserve(nb + 2); if (nb != 0) { { // Add header QVariantList item; item.push_back(false); item.push_back(i18nc("Title", "Account")); item.push_back(year); table.push_back(item); } // Add items double sum = 0; for (int i = 0; i < nb; ++i) { SKGAccountObject obj(objs.at(i)); SKGAccountObject::SKGInterestItemList oInterestList; double oInterests = 0; obj.getInterestItems(oInterestList, oInterests, year); sum += oInterests; QVariantList item; // clazy:exclude=container-inside-loop item.push_back(false); item.push_back(obj.getName()); item.push_back(oInterests); table.push_back(item); } { // Add sum QVariantList item; item.push_back(true); item.push_back(i18nc("Noun, the numerical total of a sum of values", "Total")); item.push_back(sum); table.push_back(item); } } } m_cache[cacheId] = table; } } return table; } QVariantList SKGReportBank::getBudgetTable() { QString cacheId = QStringLiteral("getBudgetTable"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); table = doc != nullptr ? doc->getBudget(getPeriod()) : QVariantList(); m_cache[cacheId] = table; } return table; } QVariantList SKGReportBank::getPortfolio() { QString cacheId = QStringLiteral("getPortfolio"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) QString period = getPeriod(); if (!period.isEmpty()) { QDate date = qMin(SKGServices::periodToDate(period), QDate::currentDate().addDays(1 - QDate::currentDate().day()).addMonths(1).addDays(-1)); auto* doc = qobject_cast(m_document); if (doc != nullptr) { SKGServices::SKGUnitInfo primary = doc->getPrimaryUnit(); // Get list of operations SKGObjectBase::SKGListSKGObjectBase objs; SKGError err = doc->getObjects(QStringLiteral("v_operation_display"), "d_date<'" % SKGServices::dateToSqlString(QDateTime(date)) % "' AND rc_unit_id IN (SELECT id FROM v_unit_display WHERE t_type='S' AND f_QUANTITYOWNED>0.01) ORDER BY t_UNIT", objs); int nb = objs.count(); if (!err && nb > 0) { table.reserve(nb + 1); QVariantList line; line << doc->getDisplay(QStringLiteral("t_symbol")) << doc->getDisplay(QStringLiteral("t_UNIT")) << i18nc("Column table title", "Quantity") << i18nc("Column table title", "Purchase amount") << i18nc("Column table title", "Initial amount") << QLocale().toString(date, QLocale::ShortFormat) << i18nc("Column table title", "Variation") << i18nc("Column table title", "Variation %"); table << QVariant(line); QVector listUnitValues; unitValues current; current.initalAmount = 0.0; current.purchaseAmount = 0.0; current.currentAmount = 0.0; current.quantity = 0.0; listUnitValues.reserve(nb); for (int i = 0; i < nb; ++i) { SKGOperationObject obj(objs.at(i)); SKGUnitObject unit; obj.getUnit(unit); if (i != 0 && current.unit != unit) { listUnitValues.push_back(current); current.initalAmount = 0.0; current.purchaseAmount = 0.0; current.currentAmount = 0.0; current.quantity = 0.0; } current.unit = unit; current.initalAmount += obj.getAmount(obj.getDate()); current.currentAmount += obj.getAmount(date); SKGObjectBase::SKGListSKGObjectBase oGroupedOperations; obj.getGroupedOperations(oGroupedOperations); oGroupedOperations.removeAll(obj); if (oGroupedOperations.count() == 1) { SKGOperationObject obj2(oGroupedOperations.at(0)); current.purchaseAmount += obj2.getAmount(obj.getDate()); } current.quantity += SKGServices::stringToDouble(obj.getAttribute(QStringLiteral("f_QUANTITY"))); } if (!current.unit.getName().isEmpty()) { listUnitValues.push_back(current); } nb = listUnitValues.count(); for (int j = 0; j < nb; ++j) { unitValues current2 = listUnitValues.at(j); SKGServices::SKGUnitInfo ui = current2.unit.getUnitInfo(); ui.Value = 1; QVariantList line2; // clazy:exclude=container-inside-loop line2 << current2.unit.getSymbol() << current2.unit.getName() << doc->formatMoney(current2.quantity, ui, false) << current2.purchaseAmount << current2.initalAmount << current2.currentAmount << current2.currentAmount - current2.initalAmount << (current2.initalAmount == 0.0 ? 0.0 : 100.0 * (current2.currentAmount - current2.initalAmount) / current2.initalAmount); table << QVariant(line2); } } } } m_cache[cacheId] = table; } return table; } QVariantList SKGReportBank::getUnitTable() { QString cacheId = QStringLiteral("getUnitTable"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) QString period = getPeriod(); if (!period.isEmpty()) { QDate date1 = SKGServices::periodToDate(getPreviousPeriod()); QDate date2 = SKGServices::periodToDate(period); auto* doc = qobject_cast(m_document); if (doc != nullptr) { SKGServices::SKGUnitInfo primary = doc->getPrimaryUnit(); SKGObjectBase::SKGListSKGObjectBase units; SKGError err = doc->getObjects(QStringLiteral("v_unit_display"), QStringLiteral("1=1 ORDER BY t_TYPENLS"), units); int nbUnits = units.count(); if (nbUnits != 0) { table.reserve(nbUnits + 1); QVariantList line; line << "sum" << doc->getDisplay(QStringLiteral("t_UNIT")) << QLocale().toString(date1, QLocale::ShortFormat) << QLocale().toString(date2, QLocale::ShortFormat) << "%" << doc->getDisplay(QStringLiteral("t_symbol")); table << QVariant(line); for (const auto& item : qAsConst(units)) { SKGUnitObject unit(item); double v1 = unit.getAmount(date1); double v2 = unit.getAmount(date2); QVariantList line2; // clazy:exclude=container-inside-loop line2 << false << unit.getName() << v1 << v2 << (100.0 * (v2 - v1) / qAbs(v1)) << unit.getSymbol(); table << QVariant(line2); } } } } m_cache[cacheId] = table; } return table; } QVariantList SKGReportBank::getAccountTable() { QString cacheId = QStringLiteral("getAccountTable"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) QString period = getPeriod(); if (!period.isEmpty()) { QDate date1 = SKGServices::periodToDate(getPreviousPeriod()); QDate date2 = SKGServices::periodToDate(period); QDate date3 = date2.addYears(-1); if (date3 == date1) { date3 = date3.addYears(-1); } auto* doc = qobject_cast(m_document); if (doc != nullptr) { SKGServices::SKGUnitInfo primary = doc->getPrimaryUnit(); SKGObjectBase::SKGListSKGObjectBase accounts; SKGError err = doc->getObjects(QStringLiteral("v_account"), QStringLiteral("1=1 ORDER BY t_TYPENLS, t_BANK, t_name"), accounts); IFOK(err) { table.push_back(QVariantList() << "sum" << doc->getDisplay(QStringLiteral("t_ACCOUNT")) << QLocale().toString(date1, QLocale::ShortFormat) << QLocale().toString(date2, QLocale::ShortFormat) << "%" << QLocale().toString(date3, QLocale::ShortFormat) << QLocale().toString(date2, QLocale::ShortFormat) << "%"); double sumTypeV1 = 0; double sumTypeV2 = 0; double sumTypeV3 = 0; double sumV1 = 0; double sumV2 = 0; double sumV3 = 0; int nbAdded = 0; QString currentType; int nb = accounts.count(); for (int i = 0; !err && i < nb; ++i) { SKGAccountObject account(accounts.at(i)); double v1 = account.getAmount(date1); double v2 = account.getAmount(date2); double v3 = account.getAmount(date3); QString type = account.getAttribute(QStringLiteral("t_TYPENLS")); bool closed = account.isClosed(); if (type != currentType) { - if (!currentType.isEmpty() && nbAdded>0) { + if (!currentType.isEmpty() && nbAdded > 0) { table.push_back(QVariantList() << true << i18nc("Noun", "Total of %1", currentType) << sumTypeV1 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV1) / qAbs(sumTypeV1)) << sumTypeV3 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV3) / qAbs(sumTypeV3)) << "" << ""); sumTypeV1 = 0; sumTypeV2 = 0; sumTypeV3 = 0; nbAdded = 0; } currentType = type; } if (!closed || qAbs(v1) > 0.01 || qAbs(v2) > 0.01 || qAbs(v3) > 0.01) { QString icon = account.getAttribute(QStringLiteral("t_ICON")); if (!icon.isEmpty()) { QString iconfile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "skrooge/images/logo/" % icon); if (!iconfile.isEmpty()) { icon = iconfile; } } table.push_back(QVariantList() << false << account.getName() << v1 << v2 << (100.0 * (v2 - v1) / qAbs(v1)) << v3 << v2 << (100.0 * (v2 - v3) / qAbs(v3)) << account.getAttribute(QStringLiteral("t_BANK")) << icon); nbAdded++; } sumTypeV1 += v1; sumTypeV2 += v2; sumTypeV3 += v3; sumV1 += v1; sumV2 += v2; sumV3 += v3; } table.push_back(QVariantList() << true << i18nc("Noun", "Total of %1", currentType) << sumTypeV1 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV1) / qAbs(sumTypeV1)) << sumTypeV3 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV3) / qAbs(sumTypeV3)) << "" << ""); table.push_back(QVariantList() << true << i18nc("Noun, the numerical total of a sum of values", "Total") << sumV1 << sumV2 << (100.0 * (sumV2 - sumV1) / qAbs(sumV1)) << sumV3 << sumV2 << (100.0 * (sumV2 - sumV3) / qAbs(sumV3)) << "" << ""); } } } m_cache[cacheId] = table; } return table; } QVariantList SKGReportBank::getBankTable() { QString cacheId = QStringLiteral("getBankTable"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) QString period = getPeriod(); if (!period.isEmpty()) { QDate date1 = SKGServices::periodToDate(getPreviousPeriod()); QDate date2 = SKGServices::periodToDate(period); QDate date3 = date2.addYears(-1); if (date3 == date1) { date3 = date3.addYears(-1); } auto* doc = qobject_cast(m_document); if (doc != nullptr) { SKGServices::SKGUnitInfo primary = doc->getPrimaryUnit(); SKGObjectBase::SKGListSKGObjectBase accounts; SKGError err = doc->getObjects(QStringLiteral("v_account"), QStringLiteral("1=1 ORDER BY t_BANK"), accounts); IFOK(err) { table.push_back(QVariantList() << "sum" << doc->getDisplay(QStringLiteral("t_BANK")) << QLocale().toString(date1, QLocale::ShortFormat) << QLocale().toString(date2, QLocale::ShortFormat) << "%" << QLocale().toString(date3, QLocale::ShortFormat) << QLocale().toString(date2, QLocale::ShortFormat) << "%"); double sumTypeV1 = 0; double sumTypeV2 = 0; double sumTypeV3 = 0; double sumV1 = 0; double sumV2 = 0; double sumV3 = 0; QString currentName; QString currentIcon; bool currentOpen = false; int nb = accounts.count(); for (int i = 0; !err && i < nb; ++i) { SKGAccountObject account(accounts.at(i)); double v1 = account.getAmount(date1); double v2 = account.getAmount(date2); double v3 = account.getAmount(date3); QString name = account.getAttribute(QStringLiteral("t_BANK")); QString icon = account.getAttribute(QStringLiteral("t_ICON")); if (!icon.isEmpty()) { QString iconfile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "skrooge/images/logo/" % icon); if (!iconfile.isEmpty()) { icon = iconfile; } } bool open = !account.isClosed(); if (name != currentName) { if (!currentName.isEmpty() && currentOpen) { table.push_back(QVariantList() << false << currentName << sumTypeV1 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV1) / qAbs(sumTypeV1)) << sumTypeV3 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV3) / qAbs(sumTypeV3)) << currentIcon); sumTypeV1 = 0; sumTypeV2 = 0; sumTypeV3 = 0; currentOpen = open; } currentName = name; currentIcon = icon; } currentOpen = currentOpen || open; sumTypeV1 += v1; sumTypeV2 += v2; sumTypeV3 += v3; sumV1 += v1; sumV2 += v2; sumV3 += v3; } if (currentOpen) { table.push_back(QVariantList() << false << currentName << sumTypeV1 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV1) / qAbs(sumTypeV1)) << sumTypeV3 << sumTypeV2 << (100.0 * (sumTypeV2 - sumTypeV3) / qAbs(sumTypeV3)) << currentIcon); } table.push_back(QVariantList() << true << i18nc("Noun, the numerical total of a sum of values", "Total") << sumV1 << sumV2 << (100.0 * (sumV2 - sumV1) / qAbs(sumV1)) << sumV3 << sumV2 << (100.0 * (sumV2 - sumV3) / qAbs(sumV3))); } } } m_cache[cacheId] = table; } return table; } QVariantList SKGReportBank::getScheduledOperations() { QString cacheId = QStringLiteral("getScheduledOperations"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) SKGObjectBase::SKGListSKGObjectBase objs; auto scheduled_operation_days_max = m_parameters.value(QStringLiteral("scheduled_operation_days_max"), QStringLiteral("30")).toString(); SKGError err = m_document->getObjects(QStringLiteral("v_recurrentoperation_display"), QStringLiteral("i_nb_times!=0 AND d_date<=date('now','+") + scheduled_operation_days_max + " day') ORDER BY d_date", objs); QDate d = QDate::currentDate().addDays(SKGServices::stringToInt(scheduled_operation_days_max)); QString dateFormatShort = QLocale::system().dateFormat(QLocale::ShortFormat); IFOK(err) { int nb = objs.count(); if (nb != 0) { table.reserve(nb); for (int i = 0; i < nb; ++i) { SKGRecurrentOperationObject obj(objs.at(i)); bool first = true; auto obj_date = obj.getDate().toString(dateFormatShort); while (true) { if (obj.getDate() > d || (obj.hasTimeLimit() && obj.getTimeLimit() == 0)) { break; } else { bool bold = false; if (obj.isWarnEnabled() && QDate::currentDate() >= obj.getDate().addDays(-obj.getWarnDays())) { bold = true; } auto name = obj.getDisplayName(); if (!first) { name = name.replace(obj_date, obj.getDate().toString(dateFormatShort)); } table.push_back(QVariantList() << bold << name << (first ? obj.getUniqueID() : QString()) << obj.getDate()); first = false; obj.setDate(obj.getNextDate()); if (obj.hasTimeLimit()) { obj.setTimeLimit(obj.getTimeLimit() - 1); } } } } } std::sort(table.begin(), table.end(), [](const QVariant & v1, const QVariant & v2) { return v1.toList().at(3).toDate() < v2.toList().at(3).toDate(); }); m_cache[cacheId] = table; } } return table; } QVariantList SKGReportBank::getMainCategoriesForPeriod() { QString cacheId = QStringLiteral("getMainCategoriesForPeriod"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); table = doc != nullptr ? doc->getMainCategories(getPeriod(), 5) : QVariantList(); m_cache[cacheId] = table; } return table; } QVariantList SKGReportBank::getMainCategoriesForPreviousPeriod() { QString cacheId = QStringLiteral("getMainCategoriesForPreviousPeriod"); QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); table = doc != nullptr ? doc->getMainCategories(getPreviousPeriod(), 5) : QVariantList(); m_cache[cacheId] = table; } return table; } QStringList SKGReportBank::get5MainCategoriesVariation() { QString cacheId = QStringLiteral("get5MainCategoriesVariation"); QStringList table = m_cache.value(cacheId).toStringList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); table = doc != nullptr ? doc->get5MainCategoriesVariationList(getPeriod(), getPreviousPeriod(), false) : QStringList(); m_cache[cacheId] = table; } return table; } QStringList SKGReportBank::get5MainCategoriesVariationIssue() { QString cacheId = QStringLiteral("get5MainCategoriesVariationIssue"); QStringList table = m_cache.value(cacheId).toStringList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); table = doc != nullptr ? doc->get5MainCategoriesVariationList(getPeriod(), getPreviousPeriod(), true) : QStringList(); m_cache[cacheId] = table; } return table; } QVariantMap SKGReportBank::getPersonalFinanceScoreDetails(bool iTransfer, bool iTracker) { KColorScheme scheme(QPalette::Normal, KColorScheme::Window); QVariantMap output; double pfs = getPersonalFinanceScore(iTransfer, iTracker); output[QStringLiteral("value")] = pfs; if (pfs < 0) { output[QStringLiteral("level")] = QStringLiteral("danger"); output[QStringLiteral("message")] = i18nc("An advice", "You must try to get out of debt."); output[QStringLiteral("color")] = scheme.foreground(KColorScheme::NegativeText).color().name().right(6); } else if (pfs >= 25) { output[QStringLiteral("level")] = QStringLiteral("success"); output[QStringLiteral("message")] = i18nc("An advice", "Congratulations, you are now financially independent."); output[QStringLiteral("color")] = scheme.foreground(KColorScheme::PositiveText).color().name().right(6); } else if (pfs >= 10) { output[QStringLiteral("level")] = QStringLiteral("success"); output[QStringLiteral("message")] = i18nc("An advice", "Congratulations, You saved up ten year’s worth of expenses."); output[QStringLiteral("color")] = scheme.foreground(KColorScheme::PositiveText).color().name().right(6); } else if (pfs >= 2) { output[QStringLiteral("level")] = QStringLiteral("warning"); output[QStringLiteral("message")] = i18nc("An advice", "You saved up %1 year’s worth of expenses. You should continue your effort.", SKGServices::intToString(pfs)); output[QStringLiteral("color")] = scheme.foreground(KColorScheme::NeutralText).color().name().right(6); } else if (pfs >= 1) { output[QStringLiteral("level")] = QStringLiteral("warning"); output[QStringLiteral("message")] = i18nc("An advice", "You saved up one year’s worth of expenses. You should maintain your effort."); output[QStringLiteral("color")] = scheme.foreground(KColorScheme::NeutralText).color().name().right(6); } else { output[QStringLiteral("level")] = QStringLiteral("warning"); output[QStringLiteral("message")] = i18nc("An advice", "You do not have debt but you have no margin. You must maintain your effort."); output[QStringLiteral("color")] = scheme.foreground(KColorScheme::NeutralText).color().name().right(6); } return output; } double SKGReportBank::getPersonalFinanceScore(bool iTransfer, bool iTracker) { double as = getAnnualSpending(iTransfer, iTracker); return (as == 0.0 ? 0.0 : getNetWorth(iTransfer, iTracker) / as); } double SKGReportBank::getAnnualSpending(bool iTransfer, bool iTracker) { QString cacheId = QStringLiteral("getAnnualSpending-") % (iTransfer ? QStringLiteral("Y") : QStringLiteral("N")) % (iTracker ? QStringLiteral("Y") : QStringLiteral("N")); double output = m_cache.value(cacheId).toDouble(); if (!m_cache.contains(cacheId)) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); if (doc != nullptr) { QString result; QDate d2 = SKGServices::periodToDate(getPeriod()); QDate d1 = d2.addYears(-1); doc->executeSingleSelectSqliteOrder("SELECT TOTAL(f_REALCURRENTAMOUNT) FROM v_suboperation_consolidated WHERE d_date BETWEEN '" % SKGServices::dateToSqlString(d1) % "' AND '" % SKGServices::dateToSqlString(d2) % "' AND t_TYPEEXPENSE='-'" % (iTransfer ? "" : " AND t_TRANSFER='N'") % (iTracker ? "" : " AND t_REFUND=''") , result); output = -SKGServices::stringToDouble(result); m_cache[cacheId] = output; } } return output; } double SKGReportBank::getNetWorth(bool iTransfer, bool iTracker) { QString cacheId = QStringLiteral("getNetWorth-") % (iTransfer ? QStringLiteral("Y") : QStringLiteral("N")) % (iTracker ? QStringLiteral("Y") : QStringLiteral("N")); double output = m_cache.value(cacheId).toDouble(); if (!m_cache.contains(cacheId)) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); if (doc != nullptr) { QString result; QDate d = SKGServices::periodToDate(getPeriod()); doc->executeSingleSelectSqliteOrder("SELECT TOTAL(f_REALCURRENTAMOUNT) FROM v_suboperation_consolidated WHERE d_date<='" % SKGServices::dateToSqlString(d) % "' " % (iTransfer ? "" : " AND t_TRANSFER='N'") % (iTracker ? "" : " AND t_REFUND=''") , result); output = SKGServices::stringToDouble(result); m_cache[cacheId] = output; } } return output; } QVariantList SKGReportBank::getIncomeVsExpenditure(bool iOnSubOperation, bool iGrouped, bool iTransfer, bool iTracker, const QString& iWhereClause1, const QString& iWhereClause2) { QString cacheId = QStringLiteral("getIncomeVsExpenditure-") % (iOnSubOperation ? QStringLiteral("Y") : QStringLiteral("N")) % (iGrouped ? QStringLiteral("Y") : QStringLiteral("N")) % (iTransfer ? QStringLiteral("Y") : QStringLiteral("N")) % (iTracker ? QStringLiteral("Y") : QStringLiteral("N")) % iWhereClause1 % iWhereClause2; QVariantList table = m_cache.value(cacheId).toList(); if (table.isEmpty()) { SKGTRACEINFUNC(10) auto* doc = qobject_cast(m_document); if (doc != nullptr) { QString tableDb = (iOnSubOperation ? QStringLiteral("v_suboperation_consolidated") : QStringLiteral("v_operation_display")); QString amount = (iOnSubOperation ? QStringLiteral("f_REALCURRENTAMOUNT") : QStringLiteral("f_CURRENTAMOUNT")); SKGStringListList listTmp; QString wc1 = iWhereClause1; if (wc1.isEmpty()) { wc1 = SKGServices::getPeriodWhereClause(getPeriod()); } QString wc2 = iWhereClause2; if (wc2.isEmpty()) { wc2 = SKGServices::getPeriodWhereClause(getPreviousPeriod()); } SKGError err = doc->executeSelectSqliteOrder( "SELECT TOTAL(" % amount % "), '1' from " % tableDb % " WHERE " % wc1 % " AND t_TYPEACCOUNT<>'L'" % (iGrouped ? "" : " AND i_group_id=0") % (iTransfer ? "" : " AND t_TRANSFER='N'") % (iTracker ? "" : (iOnSubOperation ? " AND t_REALREFUND=''" : " AND t_REFUND=''")) % " group by t_TYPEEXPENSE " % " UNION ALL " % "SELECT TOTAL(" % amount % "), '2' from " % tableDb % " WHERE " % wc2 % " AND t_TYPEACCOUNT<>'L'" % (iGrouped ? "" : " AND i_group_id=0") % (iTransfer ? "" : " AND t_TRANSFER='N'") % (iTracker ? "" : (iOnSubOperation ? " AND t_REALREFUND=''" : " AND t_REFUND=''")) % " group by t_TYPEEXPENSE ", listTmp); IFOK(err) { double income_previous_period = 0; double expense_previous_period = 0; double income_period = 0; double expense_period = 0; int nbval = listTmp.count(); for (int i = 1; i < nbval; ++i) { // Ignore header QString m = listTmp.at(i).at(1); double v = SKGServices::stringToDouble(listTmp.at(i).at(0)); if (v > 0 && m == QStringLiteral("1")) { income_period = v; } else if (v < 0 && m == QStringLiteral("1")) { expense_period = v; } else if (v > 0 && m == QStringLiteral("2")) { income_previous_period = v; } else if (v < 0 && m == QStringLiteral("2")) { expense_previous_period = v; } } double saving_previous_period = income_previous_period + expense_previous_period; double saving_period = income_period + expense_period; table.push_back(QVariantList() << QStringLiteral("sum") << QLatin1String("") << getPreviousPeriod() << getPeriod() << QStringLiteral("max")); table.push_back(QVariantList() << false << doc->getDisplay(QStringLiteral("f_CURRENTAMOUNT_INCOME")) << qAbs(income_previous_period) << qAbs(income_period)); table.push_back(QVariantList() << false << doc->getDisplay(QStringLiteral("f_CURRENTAMOUNT_EXPENSE")) << qAbs(expense_previous_period) << qAbs(expense_period)); table.push_back(QVariantList() << true << i18nc("Noun", "Savings possible") << saving_previous_period << saving_period); table.push_back(QVariantList() << true << i18nc("Noun", "Max") << qMax(qAbs(income_previous_period), qAbs(expense_previous_period)) << qMax(qAbs(income_period), qAbs(expense_period))); } m_cache[cacheId] = table; } } return table; } void SKGReportBank::addItemsInMapping(QVariantHash& iMapping) { SKGReport::addItemsInMapping(iMapping); iMapping.insert(QStringLiteral("about_forumpage"), QStringLiteral("https://forum.kde.org/viewforum.php?f=210")); iMapping.insert(QStringLiteral("about_newspage"), QStringLiteral("https://skrooge.org/news")); iMapping.insert(QStringLiteral("about_operationpage"), QStringLiteral("skg://Skrooge_operation_plugin/")); iMapping.insert(QStringLiteral("about_accountpage"), QStringLiteral("skg://Skrooge_bank_plugin/")); iMapping.insert(QStringLiteral("about_importurl"), QStringLiteral("skg://import_operation/")); iMapping.insert(QStringLiteral("about_maintext"), i18nc("The main text of skrooge", "Skrooge allows you to keep a hold on your expenses, by tracking and budgeting them.
" "What should you do now ?
" "" "

You may come back to this page any time by closing all tabs.
" "For more information about using Skrooge, check the Skrooge website.

" "

We hope that you will enjoy Skrooge

" " The Skrooge Team", iMapping[QStringLiteral("about_accountpage")].toString(), iMapping[QStringLiteral("about_operationpage")].toString(), iMapping[QStringLiteral("about_importurl")].toString())); iMapping.insert(QStringLiteral("logo"), QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("icons/breeze/apps/48/skrooge.svg"))).url()); iMapping.insert(QStringLiteral("logo_black"), QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("icons/breeze/apps/48/skrooge-black.svg"))).url()); iMapping.insert(QStringLiteral("title_main"), i18nc("A monthly report title", "Report for %1", getPeriod())); iMapping.insert(QStringLiteral("title_budget"), i18nc("A monthly report title", "Budget")); iMapping.insert(QStringLiteral("title_main_categories"), i18nc("A monthly report title", "5 main categories of expenditure")); iMapping.insert(QStringLiteral("title_variations"), i18nc("A monthly report title", "5 main variations")); iMapping.insert(QStringLiteral("title_account"), i18nc("A monthly report title", "Amounts in accounts")); iMapping.insert(QStringLiteral("title_unit"), i18nc("A monthly report title", "Amounts of units")); iMapping.insert(QStringLiteral("title_advice"), i18nc("A monthly report title", "Advice")); iMapping.insert(QStringLiteral("title_portfolio"), i18nc("A monthly report title", "Stock portfolio")); iMapping.insert(QStringLiteral("title_interests"), i18nc("A monthly report title", "Estimated interests")); iMapping.insert(QStringLiteral("title_alarms"), i18nc("A monthly report title", "Alarms")); iMapping.insert(QStringLiteral("title_highlighted"), i18nc("A monthly report title", "Highlighted operations")); iMapping.insert(QStringLiteral("title_networth"), i18nc("A monthly report title", "Net Worth")); iMapping.insert(QStringLiteral("title_annual_spending"), i18nc("A monthly report title", "Annual Spending")); iMapping.insert(QStringLiteral("title_personal_finance_score"), i18nc("A monthly report title", "Personal Finance Score")); iMapping.insert(QStringLiteral("msg_no_variation"), i18nc("A monthly report message", "No variation found.")); iMapping.insert(QStringLiteral("msg_no_scheduled"), i18nc("A monthly report message", R"(No scheduled operations defined on the "Scheduled operations" page.)", "skg://Skrooge_scheduled_plugin/")); iMapping.insert(QStringLiteral("msg_no_highlighted"), i18nc("A monthly report message", R"(No highlighted operations defined on the "Operations" page.)", "skg://Skrooge_operation_plugin/")); iMapping.insert(QStringLiteral("msg_no_budget"), i18nc("A monthly report message", R"(No budget defined on the "Budget" page.)", "skg://Skrooge_budget_plugin/")); iMapping.insert(QStringLiteral("msg_no_share"), i18nc("A monthly report message", R"(No share defined on the "Unit" page.)", "skg://Skrooge_unit_plugin/")); iMapping.insert(QStringLiteral("msg_amount_unit_date"), i18nc("A monthly report message", "All amounts are calculated using the unit rates of the last day of the corresponding period.")); } diff --git a/skgbasegui/skgmainpanel.cpp b/skgbasegui/skgmainpanel.cpp index 9e12ac4db..e11e1c3c3 100644 --- a/skgbasegui/skgmainpanel.cpp +++ b/skgbasegui/skgmainpanel.cpp @@ -1,2743 +1,2745 @@ /*************************************************************************** * Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ /** @file * This file defines classes skgmainpanel. * * @author Stephane MANKOWSKI / Guillaume DE BURE */ #include "skgmainpanel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef KActivities_FOUND #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // std::sort #include "skgdefine.h" #include "skginterfaceplugin.h" #include "skgservices.h" #include "skgtraces.h" #include "skgtransactionmng.h" #include "skgtreeview.h" #include "skgwebview.h" #include "skgzoomselector.h" struct doublePointer { void* p1; void* p2; }; struct historyPage { SKGTabPage::SKGPageHistoryItem current; SKGTabPage::SKGPageHistoryItemList next; SKGTabPage::SKGPageHistoryItemList previous; }; struct actionDetails { QPointer action; QStringList tables; int min{}; int max{}; int ranking{}; bool focus{}; }; class SKGMainPanelPrivate { public: Ui::skgmainpanel_base ui{}; Ui::skgmainpanel_pref uipref{}; SKGTabWidget* m_tabWidget; QSplashScreen* m_splashScreen; SKGDocument* m_currentDocument; QList m_pluginsList; QMap m_registeredGlogalAction; QList m_historyClosedPages; QMenu* m_contextMenu; QAction* m_actHideContextItem; QAction* m_actShowAllContextItems; QAction* m_actDelete; QAction* m_closePageAction; QAction* m_closeAllOtherPagesAction; QAction* m_switchPinState; QAction* m_saveDefaultStateAction; QAction* m_resetDefaultStateAction; QAction* m_overwriteBookmarkStateAction; QAction* m_configureAction; QAction* m_enableEditorAction; QAction* m_fullScreenAction; QAction* m_actLock; QAction* m_actUnLock; QAction* m_reopenLastClosed; KStatusNotifierItem* m_kSystemTrayIcon; QLabel* m_kNormalMessage; SKGZoomSelector* m_zoomSelector; KToolBarPopupAction* m_previousAction; KToolBarPopupAction* m_nextAction; KToolBarPopupAction* m_buttonMenuAction; KToggleAction* m_showMenuBarAction; QMenu* m_previousMenu; QMenu* m_nextMenu; QMenu* m_buttonMenu; QWidget* m_mainWidget; QVBoxLayout* m_mainLayout{}; doublePointer m_progressObjects{}; bool m_middleClick; bool m_saveOnClose; QString m_fileName; SKGWidget* m_widgetHavingSelection; QStringList m_tipsOfTheDay; #ifdef KActivities_FOUND KActivities::ResourceInstance* m_activityResourceInstance; #endif static bool m_currentActionCanceled; static SKGMainPanel* m_mainPanel; SKGMainPanelPrivate() { m_actHideContextItem = nullptr; m_actShowAllContextItems = nullptr; m_actDelete = nullptr; m_closePageAction = nullptr; m_closeAllOtherPagesAction = nullptr; m_switchPinState = nullptr; m_saveDefaultStateAction = nullptr; m_resetDefaultStateAction = nullptr; m_overwriteBookmarkStateAction = nullptr; m_configureAction = nullptr; m_enableEditorAction = nullptr; m_fullScreenAction = nullptr; m_actLock = nullptr; m_actUnLock = nullptr; m_kSystemTrayIcon = nullptr; m_kNormalMessage = nullptr; m_zoomSelector = nullptr; m_previousAction = nullptr; m_nextAction = nullptr; m_buttonMenuAction = nullptr; m_mainWidget = nullptr; m_mainLayout = nullptr; m_middleClick = false; m_saveOnClose = false; m_widgetHavingSelection = nullptr; m_tabWidget = nullptr; m_splashScreen = nullptr; m_currentDocument = nullptr; m_contextMenu = nullptr; m_reopenLastClosed = nullptr; m_showMenuBarAction = nullptr; m_previousMenu = nullptr; m_nextMenu = nullptr; m_buttonMenu = nullptr; m_progressObjects.p1 = nullptr; m_progressObjects.p2 = nullptr; #ifdef KActivities_FOUND m_activityResourceInstance = nullptr; #endif } static int progressBarCallBack(int iPos, qint64 iTime, const QString& iName, void* iProgressBar) { Q_UNUSED(iTime) QProgressBar* progressBar = nullptr; QPushButton* button = nullptr; auto* pointers = static_cast(iProgressBar); if (pointers != nullptr) { progressBar = static_cast(pointers->p1); button = static_cast(pointers->p2); } bool visible = (iPos > 0 && iPos <= 100); if (progressBar != nullptr) { QString commonFormat = QStringLiteral("%p%"); /*if (iPos > 0) { * qint64 estimatedTime = 100 * iTime / iPos; * qint64 remainingTime = estimatedTime - iTime; * commonFormat = commonFormat % " - " % i18nc("To print a remaining time (in seconde) / estimated time (in second)", "%1s / %2s", * SKGServices::intToString(remainingTime / 1000), * SKGServices::intToString(estimatedTime / 1000)); }*/ progressBar->setFormat(iName.isEmpty() ? commonFormat : commonFormat % '\n' % iName); progressBar->setValue(iPos); progressBar->setVisible(visible); if (iPos == 100) { QTimer::singleShot(300, Qt::CoarseTimer, progressBar, &QProgressBar::hide); } progressBar->setToolTip(iName); QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/org/") + KAboutData::applicationData().componentName() + QLatin1String("/UnityLauncher"), QStringLiteral("com.canonical.Unity.LauncherEntry"), QStringLiteral("Update")); message << "application://org.kde.skrooge.desktop"; QVariantMap setProperty; if (iPos == 100) { setProperty.insert(QStringLiteral("progress"), 0.0); setProperty.insert(QStringLiteral("progress-visible"), false); } else { setProperty.insert(QStringLiteral("progress"), static_cast(iPos / 100.0)); setProperty.insert(QStringLiteral("progress-visible"), true); } message << setProperty; QDBusConnection::sessionBus().send(message); } if (button != nullptr) { button->setVisible(visible); if (iPos == 100) { QTimer::singleShot(300, Qt::CoarseTimer, button, &QPushButton::hide); } } SKGMainPanelPrivate::m_currentActionCanceled = false; if (iPos != 0 && iPos != 100) { qApp->processEvents(QEventLoop::AllEvents, 500); } return (SKGMainPanelPrivate::m_currentActionCanceled ? 1 : 0); } static bool adviceLessThan(const SKGAdvice& s1, const SKGAdvice& s2) { if (s1.getPriority() == s2.getPriority()) { return (s1.getShortMessage() > s2.getShortMessage()); } return (s1.getPriority() > s2.getPriority()); } static void setAttribute(QDomElement& iRoot, const QString& iPath, const QString& iValue) { int pos = iPath.indexOf('.'); if (pos == -1) { iRoot.setAttribute(iPath, iValue); } else { QString newElementName = iPath.left(pos); QString newAttribue = iPath.right(iPath.count() - pos - 1); QDomDocument doc(QStringLiteral("SKGML")); doc.setContent(iRoot.attribute(newElementName)); QDomElement root = doc.documentElement(); if (root.isNull()) { root = doc.createElement(QStringLiteral("parameters")); doc.appendChild(root); } setAttribute(root, newAttribue, iValue); iRoot.setAttribute(newElementName, doc.toString()); } } void refreshTabPosition() { m_tabWidget->setTabPosition(static_cast(skgbasegui_settings::main_tabs_position())); } void rebuildSystemTray() { if (skgbasegui_settings::icon_in_system_tray()) { if (m_kSystemTrayIcon == nullptr) { m_kSystemTrayIcon = new KStatusNotifierItem(m_mainPanel); m_kSystemTrayIcon->setStandardActionsEnabled(true); m_kSystemTrayIcon->setAssociatedWidget(m_mainPanel); KAboutData about = KAboutData::applicationData(); m_kSystemTrayIcon->setIconByName(about.programIconName()); } } else { if (m_kSystemTrayIcon != nullptr) { delete m_kSystemTrayIcon; m_kSystemTrayIcon = nullptr; } } } }; bool SKGMainPanelPrivate::m_currentActionCanceled = false; SKGMainPanel* SKGMainPanelPrivate::m_mainPanel = nullptr; SKGMainPanel::SKGMainPanel(QSplashScreen* iSplashScreen, SKGDocument* iDocument) : d(new SKGMainPanelPrivate) { SKGTRACEINFUNC(1) d->m_tabWidget = new SKGTabWidget(this); d->m_splashScreen = iSplashScreen; d->m_currentDocument = iDocument; setComponentName(QStringLiteral("skg"), KAboutData::applicationData().displayName()); setObjectName(qApp->applicationDisplayName()); // Set main panel SKGMainPanelPrivate::m_mainPanel = this; auto w = new QScrollArea(this); w->setFrameShape(QFrame::NoFrame); w->setFocusPolicy(Qt::NoFocus); d->m_mainLayout = new QVBoxLayout(w); d->m_mainLayout->setSpacing(0); d->m_mainLayout->setContentsMargins(0, 0, 0, 0); d->m_mainLayout->addWidget(d->m_tabWidget); d->ui.setupUi(this); // setMainWidget(new QLabel("hello")); // Initialize settings KSharedConfigPtr config = KSharedConfig::openConfig(); KConfigGroup prefskg = config->group("Main Panel"); int option = prefskg.readEntry("update_modified_contexts", 100); if (option == 100) { // First call, we set default values prefskg.writeEntry("update_modified_contexts", 2, KConfigBase::Normal); // NEVER: set following setting KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateContextOnClose"), KMessageBox::No); SKGTRACEL(1) << "update_modified_contexts set to NEVER" << endl; SKGTRACEL(1) << "updateContextOnClose set to No" << endl; } option = prefskg.readEntry("update_modified_bookmarks", 100); if (option == 100) { // First call, we set default values prefskg.writeEntry("update_modified_bookmarks", 2, KConfigBase::Normal); // NEVER: set following setting KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateBookmarkOnClose"), KMessageBox::No); SKGTRACEL(1) << "update_modified_bookmarks set to NEVER" << endl; SKGTRACEL(1) << "updateBookmarkOnClose set to No" << endl; } // Search plugins KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("SKG GUI/Plugin")); // Load plugins int nb = offers.count(); SKGTRACEL(1) << nb << " plugins found" << endl; if (d->m_splashScreen != nullptr) { d->m_splashScreen->showMessage(i18nc("Splash screen message", "Loading plugins..."), Qt::AlignLeft, QColor(221, 130, 8)); // krazy:exclude=qmethods } SKGError err; QStringList listAuthors; QStringList listTasks; QStringList listEmails; QStringList listOscs; for (int i = 0; i < nb; ++i) { KService::Ptr service = offers.at(i); QString name = service->name(); QString version = service->property(QStringLiteral("X-KDE-PluginInfo-Version"), QVariant::String).toString(); QString id = service->property(QStringLiteral("X-Krunner-ID"), QVariant::String).toString(); QString msg = i18nc("Splash screen message", "Loading plugin %1/%2: %3...", i + 1, nb, name); SKGTRACEL(1) << msg << endl; if (d->m_splashScreen != nullptr) { d->m_splashScreen->showMessage(msg, Qt::AlignLeft, QColor(221, 130, 8)); // krazy:exclude=qmethods } KPluginLoader loader(service->library()); if (version.isEmpty() || SKGServices::stringToDouble(version) < 1) { SKGTRACE << "WARNING: plugin [" << name << "] not loaded because of version too old (<1)" << endl; } else { KPluginFactory* factory2 = loader.factory(); if (factory2 != nullptr) { auto* pluginInterface = factory2->create (this); if (pluginInterface != nullptr) { if (pluginInterface->isEnabled() && pluginInterface->setupActions(getDocument())) { // Add plugin in about QStringList listOfAuthors; QStringList listOfEmails; QStringList listOfPlugins; QString author = service->property(QStringLiteral("X-KDE-PluginInfo-Author"), QVariant::String).toString(); QString email = service->property(QStringLiteral("X-KDE-PluginInfo-Email"), QVariant::String).toString(); if (!author.isEmpty()) { listOfAuthors.push_back(author); listOfEmails.push_back(email); listOfPlugins.push_back(name); } const auto subPlugins = pluginInterface->subPlugins(); for (const QString& subPlugin : subPlugins) { KService::List subOffers = KServiceTypeTrader::self()->query(subPlugin); int nbSubOffers = subOffers.count(); for (int j = 0; j < nbSubOffers; ++j) { KService::Ptr subService = subOffers.at(j); QString author2 = subService->property(QStringLiteral("X-KDE-PluginInfo-Author"), QVariant::String).toString(); QString email2 = subService->property(QStringLiteral("X-KDE-PluginInfo-Email"), QVariant::String).toString(); if (!author2.isEmpty()) { listOfAuthors.push_back(author2); listOfEmails.push_back(email2); listOfPlugins.push_back(subService->name()); } } } int nbAuthors = listOfAuthors.count(); for (int j = 0; j < nbAuthors; ++j) { QString authorId; QString author = listOfAuthors.at(j); QStringList authors = SKGServices::splitCSVLine(author, ','); if (authors.count() == 2) { author = authors.at(0); authorId = authors.at(1); } int pos2 = listAuthors.indexOf(author); if (pos2 == -1) { listAuthors.push_back(author); listTasks.push_back(i18n("Developer of plugin '%1'", listOfPlugins.at(j))); listEmails.push_back(listOfEmails.at(j)); listOscs.push_back(authorId); } else { listTasks[pos2] += i18n(", '%1'", listOfPlugins.at(j)); } } // Store plugin int nbplugin = d->m_pluginsList.count(); int pos3 = nbplugin; for (int j = nbplugin - 1; j >= 0; --j) { if (pluginInterface->getOrder() < d->m_pluginsList.at(j)->getOrder()) { pos3 = j; } } d->m_pluginsList.insert(pos3, pluginInterface); pluginInterface->setObjectName(id); // Add tips d->m_tipsOfTheDay += pluginInterface->tips(); } } } else { QString msg2 = i18nc("An information message", "Loading plugin %1 failed because the factory could not be found in %2: %3", id, service->library(), loader.errorString()); getDocument()->sendMessage(msg2); SKGTRACEL(1) << "WARNING:" << msg2 << endl; } } } // Add credits KAboutData about = KAboutData::applicationData(); nb = listAuthors.count(); for (int i = 0; i < nb; ++i) { about.addCredit(listAuthors.at(i), listTasks.at(i), listEmails.at(i), QLatin1String(""), listOscs.at(i)); } KAboutData::setApplicationData(about); // accept dnd setAcceptDrops(true); // tell the KXmlGuiWindow that this is indeed the main widget setCentralWidget(w); d->refreshTabPosition(); d->m_tabWidget->setMovable(true); d->m_tabWidget->setTabsClosable(true); d->m_tabWidget->setUsesScrollButtons(true); d->m_tabWidget->tabBar()->setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); d->m_tabWidget->setDocumentMode(true); d->m_tabWidget->show(); // System tray d->rebuildSystemTray(); // then, setup our actions setupActions(); displayErrorMessage(err); // Add a status bar statusBar()->show(); QPalette palette2 = QApplication::palette(); palette2.setColor(QPalette::Base, Qt::transparent); d->ui.kContextList->setPalette(palette2); QAction* toggle = d->ui.kDockContext->toggleViewAction(); QAction* panelAction = actionCollection()->addAction(QStringLiteral("view_context")); registerGlobalAction(QStringLiteral("view_context"), panelAction); panelAction->setCheckable(true); panelAction->setChecked(toggle->isChecked()); panelAction->setText(toggle->text()); actionCollection()->setDefaultShortcut(panelAction, Qt::SHIFT + Qt::Key_F9); connect(panelAction, &QAction::triggered, toggle, &QAction::trigger); connect(toggle, &QAction::toggled, panelAction, &QAction::setChecked); QAction* toggle2 = d->ui.kDockMessages->toggleViewAction(); QAction* panelAction2 = actionCollection()->addAction(QStringLiteral("view_messages")); registerGlobalAction(QStringLiteral("view_messages"), panelAction2); panelAction2->setCheckable(true); panelAction2->setChecked(toggle2->isChecked()); panelAction2->setText(toggle2->text()); actionCollection()->setDefaultShortcut(panelAction2, Qt::SHIFT + Qt::Key_F8); connect(panelAction2, &QAction::triggered, toggle2, &QAction::trigger); connect(toggle2, &QAction::toggled, panelAction2, &QAction::setChecked); auto contextMenu = new KSelectAction(SKGServices::fromTheme(QStringLiteral("tab-new")), i18nc("Noun", "Pages"), this); registerGlobalAction(QStringLiteral("view_contextmenu"), contextMenu); // Add plugin in client in right order QList pageNotVisible; KConfigGroup prefContextVisibility = config->group("Context Visibility"); int shortCutIndex = 0; QString shortCutPrefix = QStringLiteral("Ctrl+"); int nbplugin = d->m_pluginsList.count(); QList contextActionList; for (int j = 0; j < nbplugin; ++j) { SKGInterfacePlugin* pluginInterface = d->m_pluginsList.at(j); if (pluginInterface != nullptr) { // Creation of the item QString title = pluginInterface->title(); SKGTRACEL(1) << "Add plugin (" << pluginInterface->getOrder() << ") : " << title << endl; if (!title.isEmpty()) { // Add menu item with shortcuts if (pluginInterface->isInPagesChooser()) { bool visible = prefContextVisibility.readEntry(pluginInterface->objectName(), true); QIcon icon = SKGServices::fromTheme(pluginInterface->icon()); auto contextItem = new QListWidgetItem(icon, title); contextItem->setStatusTip(pluginInterface->statusTip()); contextItem->setToolTip(pluginInterface->toolTip()); contextItem->setData(12, j); // context item ==> plugin int page2 = d->ui.kContextList->count(); pluginInterface->setProperty("contextItem", page2); // plugin ==> context item d->ui.kContextList->addItem(contextItem); QAction* newAction = contextMenu->addAction(icon, title); if (newAction != nullptr) { newAction->setCheckable(false); newAction->setData(page2); contextItem->setData(15, QVariant::fromValue(static_cast(newAction))); // context item ==> action if (!shortCutPrefix.isEmpty()) { ++shortCutIndex; if (shortCutIndex == 10) { shortCutIndex = 0; if (shortCutPrefix == QStringLiteral("Ctrl+")) { shortCutPrefix += QStringLiteral("Alt+"); } else { shortCutPrefix = QLatin1String(""); } } if (!shortCutPrefix.isEmpty()) { actionCollection()->setDefaultShortcut(newAction, QString(shortCutPrefix % SKGServices::intToString(shortCutIndex))); } } connect(newAction, &QAction::triggered, this, &SKGMainPanel::onOpenContext); contextActionList.append(newAction); if (!visible) { pageNotVisible.push_back(contextItem); } // Register action QString id = "page_" % pluginInterface->objectName(); registerGlobalAction(id, newAction); registerGlobalAction(id, newAction); } } // Create dock if needed QDockWidget* dockWidget = pluginInterface->getDockWidget(); if (dockWidget != nullptr) { addDockWidget(Qt::LeftDockWidgetArea, dockWidget); tabifyDockWidget(d->ui.kDockContext, dockWidget); tabifyDockWidget(dockWidget, d->ui.kDockContext); } } } } // Lock docs if needed KConfigGroup pref = getMainConfigGroup(); if (pref.readEntry("docks_locked", false)) { onLockDocks(); } if (!pref.readEntry("first_launch", false)) { this->setWindowState(windowState() | Qt::WindowMaximized); pref.writeEntry("first_launch", true); } // a call to KXmlGuiWindow::setupGUI() populates the GUI // with actions, using KXMLGUI. // It also applies the saved mainwindow settings, if any, and ask the // mainwindow to automatically save settings if changed: window size, // toolbar position, icon size, etc. setupGUI(Default, QStringLiteral("skgmainpanel.rc")); plugActionList(QStringLiteral("context_actionlist"), contextActionList); for (int j = 0; j < nbplugin; ++j) { SKGInterfacePlugin* pluginInterface = d->m_pluginsList.at(j); if (pluginInterface != nullptr) { QString title = pluginInterface->title(); SKGTRACEL(1) << "Add plugin client (" << pluginInterface->getOrder() << ") : " << title << endl; guiFactory()->addClient(pluginInterface); } } // Hide items in context nb = pageNotVisible.count(); for (int i = 0; i < nb; ++i) { setContextVisibility(pageNotVisible.at(i), false); } // Set status bar d->m_kNormalMessage = new QLabel(this); d->m_kNormalMessage->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred)); auto kProgressBar = new QProgressBar(this); kProgressBar->setObjectName(QStringLiteral("kProgressBar")); kProgressBar->setValue(0); kProgressBar->setMinimumSize(100, 20); QSizePolicy sizePolicyProgessBar(QSizePolicy::Fixed, QSizePolicy::Expanding); kProgressBar->setSizePolicy(sizePolicyProgessBar); kProgressBar->setToolTip(i18nc("Widget description", "Progress of the current action")); QFont f = kProgressBar->font(); f.setPointSize(6.0); kProgressBar->setFont(f); kProgressBar->setVisible(false); kProgressBar->setAlignment(Qt::AlignTop | Qt::AlignHCenter); kProgressBar->setRange(0, 100); d->m_zoomSelector = new SKGZoomSelector(this); d->m_zoomSelector->setSizePolicy(sizePolicyProgessBar); connect(d->m_zoomSelector, &SKGZoomSelector::changed, this, &SKGMainPanel::onZoomChanged); statusBar()->addWidget(d->m_kNormalMessage, 1); statusBar()->addPermanentWidget(kProgressBar); // Set Cancel button auto kCancelButton = new QPushButton(); kCancelButton->setObjectName(QStringLiteral("kCancelButton")); kCancelButton->setIcon(SKGServices::fromTheme(QStringLiteral("media-playback-stop"))); kCancelButton->setToolTip(i18nc("Widget description", "Cancel the current action")); kCancelButton->setStatusTip(i18nc("Widget description", "Cancel the current action")); kCancelButton->setVisible(false); connect(kCancelButton, &QPushButton::clicked, this, &SKGMainPanel::onCancelCurrentAction); // d->ui.kClearMessageBtn->setIcon(SKGServices::fromTheme(QStringLiteral("edit-clear"))); connect(d->ui.kClearMessageBtn, &QPushButton::clicked, this, &SKGMainPanel::onClearMessages); // Add special button in toolbar KToolBar* tb = toolBar(); if (tb != nullptr) { auto label = new QLabel(this); QSizePolicy sizePolicyLabel(QSizePolicy::Expanding, QSizePolicy::Preferred); sizePolicyLabel.setHorizontalStretch(0); sizePolicyLabel.setVerticalStretch(0); sizePolicyLabel.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); label->setSizePolicy(sizePolicyLabel); tb->addWidget(label); tb->addAction(d->m_buttonMenuAction); } statusBar()->addPermanentWidget(kCancelButton); statusBar()->addPermanentWidget(d->m_zoomSelector); // Set progress bar call back if (getDocument() != nullptr) { d->m_progressObjects.p1 = static_cast(kProgressBar); d->m_progressObjects.p2 = static_cast(kCancelButton); getDocument()->setProgressCallback(&SKGMainPanelPrivate::progressBarCallBack, static_cast(&d->m_progressObjects)); } // Connection if (getDocument() != nullptr) { connect(getDocument(), &SKGDocument::transactionSuccessfullyEnded, this, &SKGMainPanel::refresh, Qt::QueuedConnection); connect(getDocument(), &SKGDocument::transactionSuccessfullyEnded, this, &SKGMainPanel::notify, Qt::QueuedConnection); } connect(d->ui.kContextList, &QListWidget::itemPressed, this, &SKGMainPanel::onBeforeOpenContext); connect(d->ui.kContextList, &QListWidget::itemPressed, this, &SKGMainPanel::onOpenContext); connect(d->m_tabWidget->tabBar(), &QTabBar::tabCloseRequested, this, &SKGMainPanel::closePageByIndex); connect(d->m_tabWidget->tabBar(), &QTabBar::tabBarClicked, this, [ = ](int index) { if ((QApplication::mouseButtons() & Qt::MidButton) != 0u) { closePageByIndex(index); } }); connect(d->m_tabWidget->tabBar(), &QTabBar::tabBarDoubleClicked, this, &SKGMainPanel::addTab); connect(d->m_tabWidget->tabBar(), &QTabBar::currentChanged, this, &SKGMainPanel::currentPageChanged); connect(this, &SKGMainPanel::currentPageChanged, this, &SKGMainPanel::refresh); connect(this, &SKGMainPanel::currentPageChanged, this, &SKGMainPanel::selectionChanged); // Refresh refresh(); d->ui.kContextList->installEventFilter(this); // Build contextual menu d->ui.kContextList->setContextMenuPolicy(Qt::CustomContextMenu); d->m_contextMenu = new QMenu(d->ui.kContextList); d->m_actHideContextItem = d->m_contextMenu->addAction(SKGServices::fromTheme(QStringLiteral("layer-visible-off")), i18nc("Verb", "Hide")); connect(d->m_actHideContextItem, &QAction::triggered, this, &SKGMainPanel::onHideContextItem); d->m_actShowAllContextItems = d->m_contextMenu->addAction(SKGServices::fromTheme(QStringLiteral("layer-visible-on")), i18nc("Verb", "Show all")); connect(d->m_actShowAllContextItems, &QAction::triggered, this, &SKGMainPanel::onShowAllContextItems); d->m_contextMenu->addSeparator(); d->m_contextMenu->addAction(getGlobalAction(QStringLiteral("tab_savedefaultstate"))); d->m_contextMenu->addAction(getGlobalAction(QStringLiteral("tab_resetdefaultstate"))); connect(d->ui.kContextList, &QListWidget::customContextMenuRequested, this, &SKGMainPanel::showMenu); #ifdef KActivities_FOUND // Initialize kactivities resource instance d->m_activityResourceInstance = new KActivities::ResourceInstance(window()->winId()); d->m_activityResourceInstance->setParent(this); #endif // Show menu bar and status bar menuBar()->show(); statusBar()->show(); notify(); // Due to sendMessage not in a transaction d->m_splashScreen = nullptr; } SKGMainPanel::~SKGMainPanel() { SKGTRACEINFUNC(1) SKGMainPanelPrivate::m_mainPanel = nullptr; disconnect(getDocument(), nullptr, this, nullptr); // close plugins int nb = d->m_pluginsList.count(); for (int i = 0; i < nb; ++i) { getPluginByIndex(i)->close(); } if (getDocument() != nullptr) { getDocument()->close(); } delete d; } void SKGMainPanel::showMenu(const QPoint iPos) { if (d->m_contextMenu != nullptr) { d->m_contextMenu->popup(d->ui.kContextList->mapToGlobal(iPos)); } } void SKGMainPanel::setContextVisibility(QListWidgetItem* iItem, bool iVisibility) { if (iItem != nullptr) { // Hide item in context iItem->setHidden(!iVisibility); // Hide corresponding action QAction* act = static_cast< QAction* >(iItem->data(15).value()); if (act != nullptr) { act->setVisible(iVisibility); } // Save state in settings SKGInterfacePlugin* plugin = getPluginByIndex(iItem->data(12).toInt()); if (plugin != nullptr) { KSharedConfigPtr config = KSharedConfig::openConfig(); KConfigGroup pref = config->group("Context Visibility"); pref.writeEntry(plugin->objectName(), iVisibility); } } } void SKGMainPanel::setContextVisibility(int iPage, bool iVisibility) { setContextVisibility(d->ui.kContextList->item(iPage), iVisibility); } void SKGMainPanel::onHideContextItem() { setContextVisibility(d->ui.kContextList->currentRow(), false); } void SKGMainPanel::onShowAllContextItems() { int nb = d->ui.kContextList->count(); for (int i = 0; i < nb; ++i) { setContextVisibility(i, true); } } SKGDocument* SKGMainPanel::getDocument() const { return d->m_currentDocument; } QStringList SKGMainPanel::processArguments(const QStringList& iArgument) { QStringList output = iArgument; for (auto plugin : qAsConst(d->m_pluginsList)) { if (plugin != nullptr) { output = plugin->processArguments(output); } } return output; } void SKGMainPanel::registerGlobalAction(const QString& iIdentifier, QAction* iAction, bool iAddInCollection, const QStringList& iListOfTable, int iMinSelection, int iMaxSelection, int iRanking, bool iSelectionMustHaveFocus) { if (iAction == nullptr) { SKGTRACE << "WARNING: registerGlobalAction(" << iIdentifier << ",nullptr)" << endl; } else { QStringList keys = d->m_registeredGlogalAction.keys(); for (const auto& id : qAsConst(keys)) { QPointer act = d->m_registeredGlogalAction.value(id).action; if ((act != nullptr) && iIdentifier != id && act != iAction && !act->shortcut().isEmpty() && act->shortcut() == iAction->shortcut()) { SKGTRACE << "WARNING: The actions [" << iAction->text() << " (" << iIdentifier << ")] and [" << act->text() << " (" << id << ")] has same shortcut [" << iAction->shortcut().toString() << "]" << endl; } } actionDetails actDetails; actDetails.action = iAction; actDetails.tables = iListOfTable; actDetails.min = iMinSelection; actDetails.max = iMaxSelection; actDetails.focus = iSelectionMustHaveFocus; actDetails.ranking = (iRanking == -1 ? 10 * (d->m_registeredGlogalAction.count() + 1) : iRanking); d->m_registeredGlogalAction[iIdentifier] = actDetails; // This connect has not been migrated on new connect mechanism to avoid crash when leaving the application connect(iAction, SIGNAL(destroyed(QObject*)), this, SLOT(unRegisterGlobalAction(QObject*))); // clazy:exclude=old-style-connect if (iAddInCollection) { QKeySequence shortCut = iAction->shortcut(); if (!shortCut.isEmpty()) { iAction->setShortcut(QKeySequence()); } actionCollection()->addAction(iIdentifier, iAction); if (!shortCut.isEmpty()) { actionCollection()->setDefaultShortcut(iAction, shortCut); } } } } void SKGMainPanel::unRegisterGlobalAction(QObject* iAction) { auto* act = qobject_cast< QAction* >(iAction); if (act != nullptr) { const auto keys = d->m_registeredGlogalAction.keys(); for (const auto& id : keys) { if (d->m_registeredGlogalAction.value(id).action == QPointer(act)) { d->m_registeredGlogalAction.remove(id); } } } } QPointer SKGMainPanel::getGlobalAction(const QString& iIdentifier, bool iWarnIfNotExist) { QAction* act = d->m_registeredGlogalAction.value(iIdentifier).action; if (act == nullptr && iWarnIfNotExist) { SKGTRACE << "WARNING: getGlobalAction(" << iIdentifier << ")=nullptr" << endl; } return act; } QList< QPointer< QAction > > SKGMainPanel::getActionsForContextualMenu(const QString& iTable) { // Filter action QVector tmp; for (const auto& actDetails : qAsConst(d->m_registeredGlogalAction)) { if (actDetails.ranking > 0 && actDetails.min > 0) { if (actDetails.tables.isEmpty() || actDetails.tables.contains(iTable)) { tmp.push_back(actDetails); } else if (actDetails.tables.count() == 1 && actDetails.tables.at(0).startsWith(QLatin1String("query:"))) { // Dynamic mode QStringList tmpListTable; getDocument()->getDistinctValues(QStringLiteral("sqlite_master"), QStringLiteral("name"), actDetails.tables.at(0).right(actDetails.tables.at(0).count() - 6), tmpListTable); if (tmpListTable.contains(iTable)) { tmp.push_back(actDetails); } } } } // Sort std::sort(tmp.begin(), tmp.end(), [&](const actionDetails & a, const actionDetails & b) { return a.ranking < b.ranking; }); // Generate output int previousGroup = -1; QList< QPointer< QAction > > output; output.reserve(tmp.count()); for (const auto& actDetails : qAsConst(tmp)) { int currentGroup = (actDetails.ranking) / 100; if (currentGroup != previousGroup) { output.push_back(nullptr); previousGroup = currentGroup; } output.push_back(actDetails.action); } return output; } QMap > SKGMainPanel::getGlobalActions() const { QMap > map; const auto keys = d->m_registeredGlogalAction.keys(); for (const auto& id : keys) { map[id] = d->m_registeredGlogalAction[id].action; } return map; } SKGInterfacePlugin* SKGMainPanel::getPluginByIndex(int iIndex) { SKGInterfacePlugin* output = nullptr; if (iIndex >= 0 && iIndex < d->m_pluginsList.count()) { output = d->m_pluginsList.value(iIndex); } return output; } SKGInterfacePlugin* SKGMainPanel::getPluginByName(const QString& iName) { SKGInterfacePlugin* output = nullptr; int nbplugin = d->m_pluginsList.count(); QString name = iName.toLower(); for (int j = 0; (output == nullptr) && j < nbplugin; ++j) { QString namep = d->m_pluginsList.at(j)->objectName().toLower(); if (namep == name || namep.replace(' ', '_') == name) { output = d->m_pluginsList.at(j); } } return output; } void SKGMainPanel::setupActions() { SKGTRACEINFUNC(1) // Std File KStandardAction::quit(this, SLOT(onQuitAction()), actionCollection()); KStandardAction::configureNotifications(this, SLOT(onConfigureNotifications()), actionCollection()); // Preferences KStandardAction::preferences(this, SLOT(optionsPreferences()), actionCollection()); // New Tab auto actAddTab = new QAction(SKGServices::fromTheme(QStringLiteral("tab-new-background")), i18nc("Noun, user action", "New Tab"), this); actionCollection()->setDefaultShortcut(actAddTab, Qt::CTRL + Qt::SHIFT + Qt::Key_W); connect(actAddTab, &QAction::triggered, this, &SKGMainPanel::addTab); registerGlobalAction(QStringLiteral("new_tab"), actAddTab, true, QStringList(), -1); // Add new tab widget auto addTabButton = new QToolButton(this); addTabButton->setIcon(actAddTab->icon()); addTabButton->setAutoRaise(true); addTabButton->raise(); addTabButton->setDefaultAction(actAddTab); addTabButton->setToolButtonStyle(Qt::ToolButtonIconOnly); addTabButton->setFocusPolicy(Qt::NoFocus); d->m_tabWidget->setCornerWidget(addTabButton); d->m_actLock = new QAction(SKGServices::fromTheme(QStringLiteral("document-encrypt")), i18nc("Verb", "Lock panels"), this); connect(d->m_actLock, &QAction::triggered, this, &SKGMainPanel::onLockDocks); registerGlobalAction(QStringLiteral("view_lock"), d->m_actLock); d->m_actUnLock = new QAction(SKGServices::fromTheme(QStringLiteral("document-decrypt")), i18nc("Verb", "Unlock panels"), this); connect(d->m_actUnLock, &QAction::triggered, this, &SKGMainPanel::onUnlockDocks); registerGlobalAction(QStringLiteral("view_unlock"), d->m_actUnLock); d->m_switchPinState = new QAction(SKGServices::fromTheme(QStringLiteral("document-encrypt")), i18nc("Noun, user action", "Pin this page"), this); connect(d->m_switchPinState, &QAction::triggered, this, [ = ] {this->switchPinPage(nullptr);}); registerGlobalAction(QStringLiteral("tab_switchpin"), d->m_switchPinState); // d->m_closePageAction = actionCollection()->addAction(KStandardAction::Close, QStringLiteral("tab_close"), this, SLOT(closeCurrentPage())); registerGlobalAction(QStringLiteral("tab_close"), d->m_closePageAction); // auto actCloseAllPages = new QAction(SKGServices::fromTheme(QStringLiteral("window-close")), i18nc("Noun, user action", "Close All"), this); actionCollection()->setDefaultShortcut(actCloseAllPages, Qt::ALT + Qt::Key_W); connect(actCloseAllPages, &QAction::triggered, this, &SKGMainPanel::closeAllPages); registerGlobalAction(QStringLiteral("tab_closeall"), actCloseAllPages, true, QStringList(), -1); // d->m_closeAllOtherPagesAction = new QAction(SKGServices::fromTheme(QStringLiteral("window-close")), i18nc("Noun, user action", "Close All Other"), this); actionCollection()->setDefaultShortcut(d->m_closeAllOtherPagesAction, Qt::CTRL + Qt::ALT + Qt::Key_W); connect(d->m_closeAllOtherPagesAction, &QAction::triggered, this, [ = ] {this->closeAllOtherPages(nullptr);}); registerGlobalAction(QStringLiteral("tab_closeallother"), d->m_closeAllOtherPagesAction); // d->m_saveDefaultStateAction = new QAction(SKGServices::fromTheme(QStringLiteral("document-save")), i18nc("Noun, user action", "Save page state"), this); actionCollection()->setDefaultShortcut(d->m_saveDefaultStateAction, Qt::CTRL + Qt::ALT + Qt::Key_S); connect(d->m_saveDefaultStateAction, &QAction::triggered, this, &SKGMainPanel::saveDefaultState); registerGlobalAction(QStringLiteral("tab_savedefaultstate"), d->m_saveDefaultStateAction); // d->m_resetDefaultStateAction = new QAction(SKGServices::fromTheme(QStringLiteral("edit-clear")), i18nc("Noun, user action", "Reset page state"), this); actionCollection()->setDefaultShortcut(d->m_resetDefaultStateAction, Qt::CTRL + Qt::ALT + Qt::Key_R); connect(d->m_resetDefaultStateAction, &QAction::triggered, this, &SKGMainPanel::resetDefaultState); registerGlobalAction(QStringLiteral("tab_resetdefaultstate"), d->m_resetDefaultStateAction); // d->m_reopenLastClosed = new QAction(SKGServices::fromTheme(QStringLiteral("tab-new")), i18nc("Noun, user action", "Reopen last page closed"), this); actionCollection()->setDefaultShortcut(d->m_reopenLastClosed, Qt::CTRL + Qt::ALT + Qt::Key_T); connect(d->m_reopenLastClosed, &QAction::triggered, this, &SKGMainPanel::onReopenLastClosed); registerGlobalAction(QStringLiteral("tab_reopenlastclosed"), d->m_reopenLastClosed); // QStringList overlay; overlay.push_back(QStringLiteral("bookmarks")); d->m_overwriteBookmarkStateAction = new QAction(SKGServices::fromTheme(QStringLiteral("document-save"), overlay), i18nc("Noun, user action", "Overwrite bookmark state"), this); connect(d->m_overwriteBookmarkStateAction, &QAction::triggered, this, &SKGMainPanel::overwriteBookmarkState); actionCollection()->setDefaultShortcut(d->m_overwriteBookmarkStateAction, Qt::CTRL + Qt::ALT + Qt::Key_B); registerGlobalAction(QStringLiteral("tab_overwritebookmark"), d->m_overwriteBookmarkStateAction); // d->m_configureAction = new QAction(SKGServices::fromTheme(QStringLiteral("configure")), i18nc("Noun, user action", "Configure..."), this); connect(d->m_configureAction, &QAction::triggered, this, [ = ] {this->optionsPreferences();}); registerGlobalAction(QStringLiteral("tab_configure"), d->m_configureAction); // Menu d->m_buttonMenuAction = new KToolBarPopupAction(SKGServices::fromTheme(QStringLiteral("configure")), QLatin1String(""), this); d->m_buttonMenuAction->setToolTip(i18nc("Noun, user action", "Menu")); d->m_buttonMenu = d->m_buttonMenuAction->menu(); connect(d->m_buttonMenu, &QMenu::aboutToShow, this, &SKGMainPanel::onShowButtonMenu); d->m_buttonMenuAction->setDelayed(false); registerGlobalAction(QStringLiteral("view_menu"), d->m_buttonMenuAction); d->m_showMenuBarAction = KStandardAction::showMenubar(this, SLOT(onShowMenuBar()), actionCollection()); KConfigGroup pref = getMainConfigGroup(); d->m_showMenuBarAction->setChecked(pref.readEntry("menubar_shown", true)); QTimer::singleShot(200, Qt::CoarseTimer, this, &SKGMainPanel::onShowMenuBar); registerGlobalAction(QStringLiteral("options_show_menubar"), d->m_showMenuBarAction); // d->m_previousAction = new KToolBarPopupAction(SKGServices::fromTheme(QStringLiteral("go-previous")), i18nc("Noun, user action", "Previous"), this); connect(d->m_previousAction, &QAction::triggered, this, &SKGMainPanel::onPrevious); actionCollection()->setDefaultShortcut(d->m_previousAction, Qt::ALT + Qt::Key_Left); d->m_previousAction->setPriority(QAction::LowPriority); d->m_previousMenu = d->m_previousAction->menu(); connect(d->m_previousMenu, &QMenu::aboutToShow, this, &SKGMainPanel::onShowPreviousMenu); d->m_previousAction->setStickyMenu(false); d->m_previousAction->setData(0); registerGlobalAction(QStringLiteral("go_previous"), d->m_previousAction); // d->m_nextAction = new KToolBarPopupAction(SKGServices::fromTheme(QStringLiteral("go-next")), i18nc("Noun, user action", "Next"), this); connect(d->m_nextAction, &QAction::triggered, this, &SKGMainPanel::onNext); actionCollection()->setDefaultShortcut(d->m_nextAction, Qt::ALT + Qt::Key_Right); d->m_nextAction->setPriority(QAction::LowPriority); d->m_nextMenu = d->m_nextAction->menu(); connect(d->m_nextMenu, &QMenu::aboutToShow, this, &SKGMainPanel::onShowNextMenu); d->m_nextAction->setStickyMenu(false); d->m_nextAction->setData(0); registerGlobalAction(QStringLiteral("go_next"), d->m_nextAction); // d->m_fullScreenAction = actionCollection()->addAction(KStandardAction::FullScreen, QStringLiteral("fullscreen"), this, SLOT(onFullScreen())); registerGlobalAction(QStringLiteral("fullscreen"), d->m_fullScreenAction); // d->m_enableEditorAction = new QAction(SKGServices::fromTheme(QStringLiteral("appointment-new")), i18nc("Noun, user action", "Enable editor"), this); actionCollection()->setDefaultShortcut(d->m_enableEditorAction, Qt::CTRL + Qt::Key_Insert); connect(d->m_enableEditorAction, &QAction::triggered, this, &SKGMainPanel::enableEditor); registerGlobalAction(QStringLiteral("enable_editor"), d->m_enableEditorAction); // auto migrateSQLCipher = new QAction(SKGServices::fromTheme(QStringLiteral("run-build")), i18nc("Noun, user action", "Migrate to SQLCipher format"), this); connect(migrateSQLCipher, &QAction::triggered, this, &SKGMainPanel::onMigrateToSQLCipher); registerGlobalAction(QStringLiteral("migrate_sqlcipher"), migrateSQLCipher); // Contextual menu d->m_tabWidget->setContextMenuPolicy(Qt::ActionsContextMenu); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("new_tab"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_reopenlastclosed"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_close"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_closeall"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_closeallother"))); { auto sep = new QAction(this); sep->setSeparator(true); d->m_tabWidget->insertAction(nullptr, sep); } d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_switchpin"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_resetdefaultstate"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_savedefaultstate"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_overwritebookmark"))); d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("tab_configure"))); { auto sep = new QAction(this); sep->setSeparator(true); d->m_tabWidget->insertAction(nullptr, sep); } d->m_tabWidget->insertAction(nullptr, getGlobalAction(QStringLiteral("fullscreen"))); } void SKGMainPanel::enableEditor() { SKGTabPage* cPage = currentPage(); if (cPage != nullptr) { cPage->activateEditor(); } } void SKGMainPanel::onPrevious() { SKGError err; SKGTRACEINFUNCRC(10, err) SKGTabPage* cPage = currentPage(); if (cPage != nullptr) { // Get index in history of page to refresh int indexPrevious = qobject_cast(sender())->data().toInt(); // Get lists SKGTabPage::SKGPageHistoryItemList listPrevious = cPage->getPreviousPages(); if (indexPrevious < listPrevious.count()) { SKGTabPage::SKGPageHistoryItemList listNext = cPage->getNextPages(); SKGTabPage::SKGPageHistoryItem current = currentPageHistoryItem(); // Get item to refresh SKGTabPage::SKGPageHistoryItem item = listPrevious.at(indexPrevious); // Open page cPage = openPage(getPluginByName(item.plugin), currentPageIndex(), item.state, item.name, item.bookmarkID); if (cPage != nullptr) { cPage->setBookmarkID(item.bookmarkID); // Update lists listNext.insert(0, current); listPrevious.removeAt(indexPrevious); for (int i = 0; i < indexPrevious; ++i) { SKGTabPage::SKGPageHistoryItem itemPrevious = listPrevious.at(0); // Because the list is modified listNext.insert(0, itemPrevious); listPrevious.removeAt(0); } // Set lists cPage->setPreviousPages(listPrevious); cPage->setNextPages(listNext); } refresh(); } } } void SKGMainPanel::onShowPreviousMenu() { if (d->m_previousMenu != nullptr) { d->m_previousMenu->clear(); SKGTabPage* cPage = currentPage(); if (cPage != nullptr) { SKGTabPage::SKGPageHistoryItemList list = cPage->getPreviousPages(); int nb = list.count(); for (int i = 0; i < nb; ++i) { QAction* act = d->m_previousMenu->addAction(SKGServices::fromTheme(list.at(i).icon), list.at(i).name); if (act != nullptr) { act->setData(i); connect(act, &QAction::triggered, this, &SKGMainPanel::onPrevious); } } } } } void SKGMainPanel::onShowMenuBar() { bool test = d->m_showMenuBarAction->isChecked(); menuBar()->setVisible(test); d->m_buttonMenuAction->setVisible(!test); KConfigGroup pref = getMainConfigGroup(); pref.writeEntry("menubar_shown", test); } void SKGMainPanel::onFullScreen() { auto* p = d->m_tabWidget; if (p != nullptr) { if (!d->m_fullScreenAction->isChecked()) { // No Full screen p->setWindowState(p->windowState() & ~Qt::WindowFullScreen); // reset d->m_mainLayout->addWidget(d->m_tabWidget); } else { bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); if (atLeastOnePageOpened) { // Activate Full screen mode p->setParent(nullptr); p->setWindowFlags(p->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); p->setWindowState(p->windowState() | Qt::WindowFullScreen); // set p->show(); displayMessage(i18nc("Information message", "You can exit full screen mode with %1 or with the contextual menu", d->m_fullScreenAction->shortcut().toString())); } else { d->m_fullScreenAction->setChecked(false); displayMessage(i18nc("Information message", "At least one page must be opened to enable full screen mode"), SKGDocument::Error); } } } } void SKGMainPanel::onNext() { SKGError err; SKGTRACEINFUNCRC(10, err) SKGTabPage* cPage = currentPage(); if (cPage != nullptr) { // Get index in history of page to refresh int posNext = qobject_cast(sender())->data().toInt(); // Get lists SKGTabPage::SKGPageHistoryItemList listPrevious = cPage->getPreviousPages(); SKGTabPage::SKGPageHistoryItemList listNext = cPage->getNextPages(); SKGTabPage::SKGPageHistoryItem current = currentPageHistoryItem(); // Get item to refresh SKGTabPage::SKGPageHistoryItem item = listNext.at(posNext); // Open page cPage = openPage(getPluginByName(item.plugin), currentPageIndex(), item.state, item.name, item.bookmarkID); if (cPage != nullptr) { cPage->setBookmarkID(item.bookmarkID); // Update lists listPrevious.insert(0, current); listNext.removeAt(posNext); for (int i = 0; i < posNext; ++i) { SKGTabPage::SKGPageHistoryItem itemNext = listNext.at(0); // Because the list is modified listPrevious.insert(0, itemNext); listNext.removeAt(0); } // Set lists cPage->setPreviousPages(listPrevious); cPage->setNextPages(listNext); } refresh(); } } void SKGMainPanel::onReopenLastClosed() { SKGError err; SKGTRACEINFUNCRC(10, err) SKGTabPage::SKGPageHistoryItem current = currentPageHistoryItem(); // Get item to refresh historyPage item = d->m_historyClosedPages.takeLast(); // Open page SKGTabPage* cPage = openPage(getPluginByName(item.current.plugin), -1, item.current.state, item.current.name, item.current.bookmarkID); if (cPage != nullptr) { cPage->setBookmarkID(item.current.bookmarkID); cPage->setNextPages(item.next); cPage->setPreviousPages(item.previous); } refresh(); } void SKGMainPanel::onLockDocks() { QObjectList cs = children(); for (auto c : qAsConst(cs)) { auto* doc = qobject_cast(c); if (doc != nullptr) { doc->setFeatures(QDockWidget::NoDockWidgetFeatures); } } KConfigGroup pref = getMainConfigGroup(); pref.writeEntry("docks_locked", true); refresh(); } void SKGMainPanel::onUnlockDocks() { QObjectList cs = children(); for (auto c : qAsConst(cs)) { auto* doc = qobject_cast(c); if (doc != nullptr) { doc->setFeatures(QDockWidget::AllDockWidgetFeatures); } } KConfigGroup pref = getMainConfigGroup(); pref.writeEntry("docks_locked", false); refresh(); } void SKGMainPanel::onConfigureNotifications() { KNotifyConfigWidget::configure(this); } void SKGMainPanel::onShowNextMenu() { if (d->m_nextMenu != nullptr) { d->m_nextMenu->clear(); SKGTabPage* cPage = currentPage(); if (cPage != nullptr) { SKGTabPage::SKGPageHistoryItemList list = cPage->getNextPages(); int nb = list.count(); for (int i = 0; i < nb; ++i) { QAction* act = d->m_nextMenu->addAction(SKGServices::fromTheme(list.at(i).icon), list.at(i).name); if (act != nullptr) { act->setData(i); connect(act, &QAction::triggered, this, &SKGMainPanel::onNext); } } } } } void SKGMainPanel::onShowButtonMenu() { if (d->m_buttonMenu != nullptr) { d->m_buttonMenu->clear(); QMenuBar* mb = menuBar(); if (mb != nullptr) { d->m_buttonMenu->addActions(mb->actions()); } } } bool SKGMainPanel::queryClose() { SKGTRACEINFUNC(1) // Bug 2777697: To be sure that all page modifications are closed closeAllPages(); // Bug 2777697: bool output = queryFileClose(); // To be sure that the application is not closed in fullscreen mode if (output) { if (d->m_fullScreenAction->isChecked()) { d->m_fullScreenAction->trigger(); } } return output; } void SKGMainPanel::setSaveOnClose(bool iSaveOnClose) { d->m_saveOnClose = iSaveOnClose; } bool SKGMainPanel::queryFileClose() { SKGTRACEINFUNC(1) bool output = true; if (getDocument()->getCurrentTransaction() != 0) { displayMessage(i18nc("skgtestimportskg", "The application cannot be closed when an operation is running."), SKGDocument::Error); output = false; } else if (getDocument()->isFileModified()) { QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); int code = KMessageBox::Yes; QString fileName = getDocument()->getCurrentFileName(); QAction* save = getGlobalAction(fileName.isEmpty() ? QStringLiteral("file_save_as") : QStringLiteral("file_save")); if (save != nullptr) { if (!d->m_saveOnClose) { code = KMessageBox::questionYesNoCancel(this, i18nc("Question", "The document has been modified.\nDo you want to save it before closing?"), QString(), KGuiItem(fileName.isEmpty() ? i18nc("Question", "Save as") : i18nc("Question", "Save"), SKGServices::fromTheme(fileName.isEmpty() ? QStringLiteral("document-save-as") : QStringLiteral("document-save"))), KGuiItem(i18nc("Question", "Do not save"))); } if (code == KMessageBox::Yes) { save->trigger(); } output = (code == KMessageBox::No || code == KMessageBox::Yes); } else { code = KMessageBox::questionYesNo(this, i18nc("Question", "Current modifications will not be saved.\nDo you want to continue?")); output = (code == KMessageBox::Yes); } QApplication::restoreOverrideCursor(); } return output; } SKGObjectBase SKGMainPanel::getFirstSelectedObject() const { SKGObjectBase selection; SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); if (cPage != nullptr) { selection = cPage->getFirstSelectedObject(); } return selection; } SKGObjectBase::SKGListSKGObjectBase SKGMainPanel::getSelectedObjects() const { SKGObjectBase::SKGListSKGObjectBase selection; SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); if (cPage != nullptr) { selection = cPage->getSelectedObjects(); } return selection; } int SKGMainPanel::getNbSelectedObjects() const { int nb = 0; SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); if (cPage != nullptr) { nb = cPage->getNbSelectedObjects(); } return nb; } bool SKGMainPanel::hasSelectionWithFocus() { bool output = false; SKGWidget* cPage = (d->m_widgetHavingSelection != nullptr ? d->m_widgetHavingSelection : currentPage()); if (cPage != nullptr) { output = cPage->hasSelectionWithFocus(); } return output; } SKGAdviceList SKGMainPanel::getAdvice() const { SKGTRACEINFUNC(1) // Get list of ignored advice QString currentMonth = QDate::currentDate().toString(QStringLiteral("yyyy-MM")); QStringList ignoredAdvice = getDocument()->getParameters(QStringLiteral("advice"), "t_value='I' OR t_value='I_" % currentMonth % '\''); // Build the list of all advice by requesting all plugins SKGAdviceList globalAdviceList; int index = 0; while (index >= 0) { SKGInterfacePlugin* plugin = SKGMainPanel::getMainPanel()->getPluginByIndex(index); if (plugin != nullptr) { const auto list = plugin->advice(ignoredAdvice); for (const auto& ad : list) { if (!ignoredAdvice.contains(ad.getUUID()) && !ignoredAdvice.contains(SKGServices::splitCSVLine(ad.getUUID(), '|').at(0))) { globalAdviceList.push_back(ad); } } } else { index = -2; } ++index; } std::sort(globalAdviceList.begin(), globalAdviceList.end(), SKGMainPanelPrivate::adviceLessThan); return globalAdviceList; } KConfigGroup SKGMainPanel::getMainConfigGroup() { KSharedConfigPtr config = KSharedConfig::openConfig(); return config->group("Main Panel"); } void SKGMainPanel::optionsPreferences(const QString& iPluginName) { SKGTRACEINFUNC(1) // Compute page QString pluginName = iPluginName; if (pluginName.isEmpty()) { auto* act = qobject_cast(sender()); if (act != nullptr) { pluginName = act->property("page").toString(); } } if (pluginName.isEmpty() && (this->currentPage() != nullptr)) { pluginName = this->currentPage()->objectName(); } SKGTRACEL(1) << "Open setting page: " << pluginName << endl; // Synchronize setting with confirmation panel if (skgbasegui_settings::update_modified_bookmarks() == 0) { KMessageBox::ButtonCode confirm; bool ask = KMessageBox::shouldBeShownYesNo(QStringLiteral("updateBookmarkOnClose"), confirm); KConfigGroup pref = getMainConfigGroup(); if (ask) { pref.writeEntry("update_modified_bookmarks", 0, KConfigBase::Normal); SKGTRACEL(1) << "update_modified_bookmarks set to ASK" << endl; } else if (confirm == KMessageBox::Yes) { pref.writeEntry("update_modified_bookmarks", 1, KConfigBase::Normal); SKGTRACEL(1) << "update_modified_bookmarks set to ALWAYS" << endl; } else { pref.writeEntry("update_modified_bookmarks", 2, KConfigBase::Normal); SKGTRACEL(1) << "update_modified_bookmarks set to NEVER" << endl; } } if (skgbasegui_settings::update_modified_contexts() == 0) { KMessageBox::ButtonCode confirm; bool ask = KMessageBox::shouldBeShownYesNo(QStringLiteral("updateContextOnClose"), confirm); KConfigGroup pref = getMainConfigGroup(); if (ask) { pref.writeEntry("update_modified_contexts", 0, KConfigBase::Normal); SKGTRACEL(1) << "update_modified_contexts set to ASK" << endl; } else if (confirm == KMessageBox::Yes) { pref.writeEntry("update_modified_contexts", 1, KConfigBase::Normal); SKGTRACEL(1) << "update_modified_contexts set to ALWAYS" << endl; } else { pref.writeEntry("update_modified_contexts", 2, KConfigBase::Normal); SKGTRACEL(1) << "update_modified_contexts set to NEVER" << endl; } } skgbasegui_settings::self()->load(); if (KConfigDialog::showDialog(QStringLiteral("settings"))) { return; } auto dialog = new KConfigDialog(this, QStringLiteral("settings"), skgbasegui_settings::self()); // Add main auto w = new QWidget(); d->uipref.setupUi(w); d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Short date (%1, %2)", QLocale().toString(QDate::currentDate(), QLocale::ShortFormat), QLocale().toString(QDate::currentDate().addDays(-10), QLocale::ShortFormat))); d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Long date (%1, %2)", QLocale().toString(QDate::currentDate(), QLocale::LongFormat), QLocale().toString(QDate::currentDate().addDays(-10), QLocale::LongFormat))); d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Fancy short date (%1, %2)", KFormat().formatRelativeDate(QDate::currentDate(), QLocale::ShortFormat), KFormat().formatRelativeDate(QDate::currentDate().addDays(-10), QLocale::ShortFormat))); d->uipref.kcfg_date_format->addItem(i18nc("Date format", "Fancy long date (%1, %2)", KFormat().formatRelativeDate(QDate::currentDate(), QLocale::LongFormat), KFormat().formatRelativeDate(QDate::currentDate().addDays(-10), QLocale::LongFormat))); d->uipref.kcfg_date_format->addItem(i18nc("Date format", "ISO date (%1, %2)", QDate::currentDate().toString(Qt::ISODate), QDate::currentDate().addDays(-10).toString(Qt::ISODate))); dialog->addPage(w, skgbasegui_settings::self(), i18nc("Noun", "General"), QStringLiteral("preferences-other")); // Add plugin in client in right order int nbplugin = d->m_pluginsList.count(); for (int j = 0; j < nbplugin; ++j) { SKGInterfacePlugin* pluginInterface = getPluginByIndex(j); if (pluginInterface != nullptr) { QWidget* w2 = pluginInterface->getPreferenceWidget(); if (w2 != nullptr) { auto icon = SKGServices::fromTheme(pluginInterface->icon()); KPageWidgetItem* p = dialog->addPage(w2, pluginInterface->getPreferenceSkeleton(), pluginInterface->title(), icon.name()); if ((p != nullptr) && pluginName == pluginInterface->objectName()) { dialog->setCurrentPage(p); } } } } connect(dialog, &KConfigDialog::settingsChanged, this, &SKGMainPanel::onSettingsChanged); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); // Refresh refresh(); } void SKGMainPanel::onSettingsChanged() { SKGError err; SKGTRACEINFUNCRC(1, err) { int nb = d->m_pluginsList.count(); SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Save settings"), err, nb) // Refresh plugins for (int i = 0; !err && i < nb; ++i) { err = getPluginByIndex(i)->savePreferences(); IFOKDO(err, getDocument()->stepForward(i + 1)) } // Setting for tab position d->refreshTabPosition(); // Setting for bookmarks modification { int option = skgbasegui_settings::update_modified_bookmarks(); if (option == 0) { // ASK: remove following setting KMessageBox::enableMessage(QStringLiteral("updateBookmarkOnClose")); SKGTRACEL(1) << "updateBookmarkOnClose set to ASK" << endl; } else if (option == 1) { // ALWAYS: set following setting KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateBookmarkOnClose"), KMessageBox::Yes); SKGTRACEL(1) << "updateBookmarkOnClose set to Yes" << endl; } else { // NEVER: set following setting KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateBookmarkOnClose"), KMessageBox::No); SKGTRACEL(1) << "updateBookmarkOnClose set to No" << endl; } } { int option = skgbasegui_settings::update_modified_contexts(); if (option == 0) { // ASK: remove following setting KMessageBox::enableMessage(QStringLiteral("updateContextOnClose")); SKGTRACEL(1) << "updateContextOnClose set to ASK" << endl; } else if (option == 1) { // ALWAYS: set following setting KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateContextOnClose"), KMessageBox::Yes); SKGTRACEL(1) << "updateContextOnClose set to Yes" << endl; } else { // NEVER: set following setting KMessageBox::saveDontShowAgainYesNo(QStringLiteral("updateContextOnClose"), KMessageBox::No); SKGTRACEL(1) << "updateContextOnClose set to No" << endl; } } skgbasegui_settings::self()->load(); } // Rebuild system tray d->rebuildSystemTray(); emit settingsChanged(); // Display error displayErrorMessage(err); } void SKGMainPanel::refresh() { SKGTRACEINFUNC(1) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Show/hide main widget bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); d->m_tabWidget->setVisible(atLeastOnePageOpened); if (d->m_mainWidget != nullptr) { d->m_mainWidget->setVisible(!atLeastOnePageOpened); } // Refresh actions d->m_widgetHavingSelection = qobject_cast(sender()); SKGObjectBase selection = SKGMainPanel::getMainPanel()->getFirstSelectedObject(); int nbSelectedItems = SKGMainPanel::getMainPanel()->getNbSelectedObjects(); bool hasFocus = SKGMainPanel::getMainPanel()->hasSelectionWithFocus(); QString selectedTable = (nbSelectedItems > 0 ? selection.getRealTable() : QLatin1String("")); for (const auto& actDetails : qAsConst(d->m_registeredGlogalAction)) { QStringList tables = actDetails.tables; if (tables.count() == 1 && tables.at(0).startsWith(QLatin1String("query:"))) { // Dynamic mode getDocument()->getDistinctValues(QStringLiteral("sqlite_master"), QStringLiteral("name"), tables.at(0).right(tables.at(0).count() - 6), tables); } bool enabled = (tables.contains(selectedTable) || tables.isEmpty()) && (nbSelectedItems >= actDetails.min) && (nbSelectedItems <= actDetails.max || actDetails.max == -1) && (!actDetails.focus || hasFocus); if (enabled && nbSelectedItems == 0 && (actDetails.min == 0 || actDetails.min == -1)) { // Check if a page is opened SKGTabPage* page = SKGMainPanel::getMainPanel()->currentPage(); if (page != nullptr) { auto* view = qobject_cast(page->mainWidget()); enabled = (actDetails.min == -1 || view != nullptr); } else { enabled = false; } } if (actDetails.action != nullptr) { actDetails.action->setEnabled(enabled); } } // Refresh plugins int nb = d->m_pluginsList.count(); for (int i = 0; i < nb; ++i) { getPluginByIndex(i)->refresh(); } // Enable addTabeAction SKGTabPage* toSave = currentPage(); if (d->m_switchPinState != nullptr) { if ((toSave != nullptr) && toSave->isPin()) { d->m_switchPinState->setText(i18nc("Noun, user action", "Unpin this page")); } else { d->m_switchPinState->setText(i18nc("Noun, user action", "Pin this page")); } } if (d->m_closePageAction != nullptr) { d->m_closePageAction->setEnabled(atLeastOnePageOpened && (toSave != nullptr) && !toSave->isPin()); } if (d->m_switchPinState != nullptr) { d->m_switchPinState->setEnabled(atLeastOnePageOpened); } if (d->m_closeAllOtherPagesAction != nullptr) { d->m_closeAllOtherPagesAction->setEnabled(d->m_tabWidget->count() > 1); } if (d->m_reopenLastClosed != nullptr) { d->m_reopenLastClosed->setEnabled(!d->m_historyClosedPages.isEmpty()); } if (d->m_saveDefaultStateAction != nullptr) { d->m_saveDefaultStateAction->setEnabled((toSave != nullptr) && !toSave->getDefaultStateAttribute().isEmpty()); } if (d->m_resetDefaultStateAction != nullptr) { d->m_resetDefaultStateAction->setEnabled((toSave != nullptr) && !toSave->getDefaultStateAttribute().isEmpty()); } if (d->m_overwriteBookmarkStateAction != nullptr) { d->m_overwriteBookmarkStateAction->setEnabled((toSave != nullptr) && !toSave->getBookmarkID().isEmpty()); } if (d->m_enableEditorAction != nullptr) { d->m_enableEditorAction->setEnabled((toSave != nullptr) && toSave->isEditor()); } if (d->m_zoomSelector != nullptr) { d->m_zoomSelector->setVisible((toSave != nullptr) && toSave->isZoomable()); if (toSave != nullptr) { d->m_zoomSelector->setValue(toSave->zoomPosition()); QWidget* zoomWidget = toSave->zoomableWidget(); auto* treeView = qobject_cast(zoomWidget); if (treeView != nullptr) { disconnect(treeView, &SKGTreeView::zoomChanged, nullptr, nullptr); connect(treeView, &SKGTreeView::zoomChanged, this, [ = ](int val) { d->m_zoomSelector->setValue(val); }); } else { auto* webView = qobject_cast(zoomWidget); if (webView != nullptr) { disconnect(webView, &SKGWebView::zoomChanged, nullptr, nullptr); connect(webView, &SKGWebView::zoomChanged, this, [ = ](int val) { d->m_zoomSelector->setValue(val); }); } } } } if (d->m_actLock != nullptr) { d->m_actLock->setVisible(d->ui.kDockContext->features() == QDockWidget::AllDockWidgetFeatures); } if (d->m_actUnLock != nullptr) { d->m_actUnLock->setVisible(d->ui.kDockContext->features() == QDockWidget::NoDockWidgetFeatures); } if (d->m_previousAction != nullptr) { SKGTabPage::SKGPageHistoryItemList list; if (toSave != nullptr) { list = toSave->getPreviousPages(); } d->m_previousAction->setEnabled(!list.isEmpty()); } if (d->m_nextAction != nullptr) { SKGTabPage::SKGPageHistoryItemList list; if (toSave != nullptr) { list = toSave->getNextPages(); } d->m_nextAction->setEnabled(!list.isEmpty()); } // Set current selection of context d->ui.kContextList->clearSelection(); if (toSave != nullptr) { // Get plugin of current page SKGInterfacePlugin* plugin = getPluginByName(toSave->objectName()); int index = (plugin != nullptr ? plugin->property("contextItem").toInt() : -1); if (index != -1) { d->ui.kContextList->setCurrentItem(d->ui.kContextList->item(index)); } } // Set window title QString modified; if (getDocument()->isFileModified()) { modified += i18nc("Noun, indicate that current document is modified", " [modified]"); } if (getDocument()->isReadOnly()) { modified += i18nc("Noun, indicate that current document is loaded in read only", " [read only]"); } QString fileName = getDocument()->getCurrentFileName(); if (fileName.isEmpty()) { fileName = i18nc("Noun, default name for a new document", "Untitled"); } else { if (fileName != d->m_fileName) { // The file name has been changed onClearMessages(); d->m_fileName = fileName; #ifdef KActivities_FOUND if (!d->m_fileName.isEmpty()) { d->m_activityResourceInstance->setUri(d->m_fileName); } #endif } } setWindowTitle(i18nc("Title of the main window", "%1%2", fileName, modified)); QApplication::restoreOverrideCursor(); } SKGTabPage::SKGPageHistoryItem SKGMainPanel::currentPageHistoryItem() const { SKGTabPage::SKGPageHistoryItem cpage; int currentIndex = currentPageIndex(); SKGTabPage* cPage = currentPage(); if (currentIndex >= 0 && (cPage != nullptr)) { cpage.plugin = cPage->objectName(); SKGInterfacePlugin* plugin = SKGMainPanel::getMainPanel()->getPluginByName(cpage.plugin); if (plugin != nullptr) { cpage.name = d->m_tabWidget->tabText(currentIndex); cpage.icon = plugin->icon(); } cpage.state = cPage->getState(); cpage.bookmarkID = cPage->getBookmarkID(); } return cpage; } SKGTabPage* SKGMainPanel::openPage(SKGInterfacePlugin* plugin, int index, const QString& parameters, const QString& title, const QString& iID, bool iSetCurrent) { SKGTRACEINFUNC(1) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); bool previous = d->m_tabWidget->blockSignals(true); // If the current page is pin, then open new page SKGTabPage* cPage = currentPage(); if ((cPage != nullptr) && cPage->isPin()) { index = -1; iSetCurrent = true; } SKGTabPage* w = nullptr; SKGTabPage::SKGPageHistoryItemList previousPages; if (index != -1) { int currentIndex = currentPageIndex(); if (currentIndex >= 0 && (cPage != nullptr)) { previousPages = cPage->getPreviousPages(); previousPages.insert(0, currentPageHistoryItem()); d->m_tabWidget->removeTab(currentIndex); closePage(cPage); // Repair the history of closed page if (!d->m_historyClosedPages.isEmpty()) { d->m_historyClosedPages.removeLast(); } } } if (plugin != nullptr) { w = plugin->getWidget(); if (w != nullptr) { // Title QString title2 = (title.isEmpty() ? plugin->title() : title); w->setObjectName(plugin->objectName()); if (!iID.isEmpty()) { w->setBookmarkID(iID); } QString param = parameters; if (param.isEmpty()) { QString def = w->getDefaultStateAttribute(); if (!def.isEmpty()) { param = getDocument()->getParameter(def); } } SKGTRACEL(10) << "state=[" << param << "]" << endl; w->setState(param); connect(w, &SKGTabPage::selectionChanged, this, &SKGMainPanel::refresh); connect(w, &SKGTabPage::selectionChanged, this, &SKGMainPanel::selectionChanged); connect(w, &SKGTabPage::selectionFocusChanged, this, &SKGMainPanel::refresh); if (index == -1) { SKGTRACEINFUNC(20) d->m_tabWidget->addTab(w, SKGServices::fromTheme(plugin->icon()), title2); if (iSetCurrent) { d->m_tabWidget->setCurrentWidget(w); } } else { SKGTRACEINFUNC(20) d->m_tabWidget->insertTab(index, w, SKGServices::fromTheme(plugin->icon()), title2); if (iSetCurrent) { d->m_tabWidget->setCurrentWidget(w); } w->setPreviousPages(previousPages); SKGTabPage::SKGPageHistoryItemList empty; w->setNextPages(empty); } SKGTRACEL(1) << "opening plugin [" << plugin->objectName() << ']' << endl; Q_EMIT pageOpened(); } } else { getDocument()->sendMessage(i18nc("An information message", "Impossible to open the page because the plugin was not found"), SKGDocument::Error); notify(); // Due to sendMessage not in a transaction } // Show/hide main widget bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); d->m_tabWidget->setVisible(atLeastOnePageOpened); if (d->m_mainWidget != nullptr) { d->m_mainWidget->setVisible(!atLeastOnePageOpened); } d->m_tabWidget->blockSignals(previous); if (iSetCurrent) { Q_EMIT currentPageChanged(); } QApplication::restoreOverrideCursor(); return w; } int SKGMainPanel::currentPageIndex() const { return d->m_tabWidget->currentIndex(); } SKGTabPage* SKGMainPanel::currentPage() const { return qobject_cast< SKGTabPage* >(d->m_tabWidget->currentWidget()); } int SKGMainPanel::pageIndex(SKGTabPage* iPage) const { int nb = countPages(); for (int i = 0; i < nb; ++i) { if (page(i) == iPage) { return i; } } return -1; } QSplashScreen* SKGMainPanel::splashScreen() const { return d->m_splashScreen; } int SKGMainPanel::countPages() const { return d->m_tabWidget->count(); } SKGTabPage* SKGMainPanel::page(int iIndex) const { return qobject_cast(d->m_tabWidget->widget(iIndex)); } void SKGMainPanel::setCurrentPage(int iIndex) { d->m_tabWidget->setCurrentIndex(iIndex); } void SKGMainPanel::onBeforeOpenContext() { d->m_middleClick = ((QApplication::mouseButtons() & Qt::MidButton) != 0u); } bool SKGMainPanel::openPage(const QUrl& iUrl, bool iNewPage) { const QUrl& url(iUrl); if (url.scheme() == QStringLiteral("skg")) { // Get plugin SKGInterfacePlugin* plugin = getPluginByName(url.host()); if (plugin != nullptr) { // Open special page SKGTabPage* w = plugin->getWidget(); if (w != nullptr) { // Create xml QString path = url.path().remove('/'); QDomDocument doc(QStringLiteral("SKGML")); doc.setContent(getDocument()->getParameter(path.isEmpty() ? w->getDefaultStateAttribute() : path)); QDomElement root = doc.documentElement(); if (root.isNull()) { root = doc.createElement(QStringLiteral("parameters")); doc.appendChild(root); } auto params = QUrlQuery(url).queryItems(); for (const auto& p : qAsConst(params)) { QString value = QUrl::fromPercentEncoding(p.second.toUtf8()); SKGMainPanelPrivate::setAttribute(root, p.first, value); } // Open page openPage(plugin, iNewPage ? -1 : currentPageIndex(), doc.toString()); return true; } } else { // Trigger action QAction* act = SKGMainPanel::getMainPanel()->getGlobalAction(url.host()); if (act != nullptr) { auto params = QUrlQuery(url).queryItems(); for (const auto& p : qAsConst(params)) { QString value = QUrl::fromPercentEncoding(p.second.toUtf8()); act->setProperty(p.first.toUtf8().data(), value); } act->trigger(); return true; } } } else { QDesktopServices::openUrl(iUrl); return true; } displayErrorMessage(SKGError(ERR_ABORT, i18nc("Error message", "Unknown plugin or action [%1] in url [%2]", url.host(), iUrl.toString()))); return false; } bool SKGMainPanel::openPage() { return openPage(QString()); } bool SKGMainPanel::openPage(const QString& iUrl, bool iNewPage) { // Get the url QString urlString(iUrl); if (urlString.isEmpty()) { auto* act = qobject_cast< QAction* >(sender()); if (act != nullptr) { urlString = act->data().toString(); } } return openPage(QUrl(urlString), iNewPage); } SKGTabPage* SKGMainPanel::openPage(int iPage, bool iNewPage) { SKGTRACEINFUNC(1) SKGTRACEL(1) << "iPage=" << iPage << endl; int index = d->ui.kContextList->item(iPage)->data(12).toInt(); return openPage(getPluginByIndex(index), iNewPage ? -1 : currentPageIndex()); } void SKGMainPanel::onOpenContext() { SKGTRACEINFUNC(1) if (!(QApplication::mouseButtons() & Qt::RightButton)) { int cpage = -1; auto* s = qobject_cast(this->sender()); if (s != nullptr) { cpage = s->data().toInt(); } else { cpage = d->ui.kContextList->currentRow(); } if (cpage != -1) { openPage(cpage, ((QApplication::keyboardModifiers() &Qt::ControlModifier) != 0u) || d->m_middleClick || ((QGuiApplication::mouseButtons() & Qt::MidButton) != 0u)); } } d->m_middleClick = false; } void SKGMainPanel::switchPinPage(QWidget* iWidget) { auto* toSwitch = qobject_cast< SKGTabPage* >(iWidget); if (toSwitch == nullptr) { toSwitch = currentPage(); } if (toSwitch != nullptr) { toSwitch->setPin(!toSwitch->isPin()); Q_EMIT currentPageChanged(); } } void SKGMainPanel::closePageByIndex(int iIndex) { QWidget* w = nullptr; if (iIndex >= 0) { w = d->m_tabWidget->widget(iIndex); } else { w = d->m_tabWidget->currentWidget(); } closePage(w); } void SKGMainPanel::closeCurrentPage() { closePage(nullptr); } void SKGMainPanel::closePage(QWidget* iWidget, bool iForce) { SKGTRACEINFUNC(1) if (getDocument()->getCurrentTransaction() != 0) { QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor)); displayMessage(i18nc("Information message", "A page cannot be closed when an operation is running."), SKGDocument::Information); QApplication::restoreOverrideCursor(); } else { auto* toRemove = qobject_cast< SKGTabPage* >(iWidget); if (toRemove == nullptr) { toRemove = currentPage(); } if ((toRemove != nullptr) && toRemove->close(iForce)) { historyPage item; item.current = currentPageHistoryItem(); item.next = toRemove->getNextPages(); item.previous = toRemove->getPreviousPages(); d->m_historyClosedPages.push_back(item); delete toRemove; emit pageClosed(); } } // Show/hide main widget bool atLeastOnePageOpened = (d->m_tabWidget->count() > 0); d->m_tabWidget->setVisible(atLeastOnePageOpened); if (d->m_mainWidget != nullptr) { d->m_mainWidget->setVisible(!atLeastOnePageOpened); } if (!atLeastOnePageOpened) { d->m_fullScreenAction->setChecked(false); onFullScreen(); } } void SKGMainPanel::closeAllPages(bool iForce) { SKGTRACEINFUNC(1) bool previous = d->m_tabWidget->blockSignals(true); int nb = d->m_tabWidget->count(); for (int i = nb - 1; i >= 0; --i) { auto* w = qobject_cast< SKGTabPage* >(d->m_tabWidget->widget(i)); if ((w != nullptr) && (iForce || !w->isPin())) { closePage(w, iForce); } } d->m_tabWidget->blockSignals(previous); KMessageBox::enableMessage(QStringLiteral("closepinnedpage")); Q_EMIT currentPageChanged(); } void SKGMainPanel::closeAllOtherPages(QWidget* iWidget) { SKGTRACEINFUNC(1) bool previous = d->m_tabWidget->blockSignals(true); QWidget* toKeep = iWidget; if (toKeep == nullptr) { toKeep = currentPage(); } int nb = d->m_tabWidget->count(); for (int i = nb - 1; i >= 0; --i) { auto* w = qobject_cast< SKGTabPage* >(d->m_tabWidget->widget(i)); if ((w != nullptr) && w != toKeep && !w->isPin()) { closePage(w); } } d->m_tabWidget->blockSignals(previous); Q_EMIT currentPageChanged(); } void SKGMainPanel::saveDefaultState() { SKGTRACEINFUNC(1) SKGError err; SKGTabPage* toSave = currentPage(); if (toSave != nullptr) { // Get bookmarks uuid QString uuid = toSave->getBookmarkID(); // Reset bookmarks uuid to overwrite page state toSave->setBookmarkID(QLatin1String("")); // Overwrite toSave->overwrite(false); // Set original bookmarks uuid toSave->setBookmarkID(uuid); } } void SKGMainPanel::overwriteBookmarkState() { SKGTRACEINFUNC(1) SKGError err; SKGTabPage* toSave = currentPage(); if (toSave != nullptr) { // Get bookmarks uuid QString uuid = toSave->getBookmarkID(); if (!uuid.isEmpty()) { // Overwrite toSave->overwrite(false); } } } void SKGMainPanel::resetDefaultState() { SKGTRACEINFUNC(1) SKGError err; SKGTabPage* toSave = currentPage(); if (toSave != nullptr) { QString name = toSave->getDefaultStateAttribute(); if (!name.isEmpty()) { SKGBEGINLIGHTTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Reset default state"), err) IFOKDO(err, getDocument()->setParameter(name, QStringLiteral(""))) // Refresh panel IFOK(err) toSave->setState(QLatin1String("")); } } // status bar IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Default state has been reset"))) displayErrorMessage(err); } void SKGMainPanel::addTab() { SKGTRACEINFUNC(1) SKGTabPage* cPage = currentPage(); if (cPage != nullptr) { openPage(getPluginByName(cPage->objectName())); } } bool SKGMainPanel::eventFilter(QObject* iObject, QEvent* iEvent) { if ((iObject != nullptr) && (iEvent != nullptr) && iEvent->type() == QEvent::Resize) { auto* rEvent = dynamic_cast(iEvent); if (rEvent != nullptr) { QSize newSize = rEvent->size(); // Compute icon size int s = qMax(qMin(newSize.width() / 5, 64), 16); d->ui.kContextList->setIconSize(QSize(s, s)); } } return KXmlGuiWindow::eventFilter(iObject, iEvent); } QStringList SKGMainPanel::getTipsOfDay() const { return d->m_tipsOfTheDay; } QString SKGMainPanel::getTipOfDay() const { auto tips = getTipsOfDay(); return SKGServices::htmlToString(tips.at(qrand() % tips.size())); } void SKGMainPanel::notify(int iTransaction) { SKGTRACEINFUNC(1) SKGTRACEL(1) << "iTransaction=" << iTransaction << endl; // Notify SKGObjectBase transaction(getDocument(), QStringLiteral("doctransaction"), iTransaction); if (iTransaction == 0 || transaction.getAttribute(QStringLiteral("t_mode")) != QStringLiteral("R")) { SKGDocument::SKGMessageList msg; getDocument()->getMessages(iTransaction, msg, false); int nbMessages = msg.count(); if (nbMessages != 0) { // Build list of types SKGDocument::MessageType maxType = SKGDocument::Positive; QList listGroups; listGroups.reserve(nbMessages); for (int i = 0; i < nbMessages; ++i) { SKGDocument::SKGMessage m = msg.at(i); // if the message has an action, it can not be grouped if (!m.Action.isEmpty()) { displayMessage(m.Text, m.Type, m.Action); msg.removeAt(i); i--; nbMessages--; } else { if (listGroups.isEmpty() || m.Type != listGroups.at(listGroups.count() - 1)) { listGroups.push_back(m.Type); } if (static_cast(m.Type) >= static_cast(maxType)) { maxType = m.Type; } } } // Is the number of type acceptable? bool modeGrouped = false; if (listGroups.count() > 5 || nbMessages > 20) { // Too many group ==> simplification listGroups.clear(); listGroups.push_back(maxType); modeGrouped = true; } // Build message if (nbMessages != 0) { QString message; int indexGroup = 0; for (int i = 0; i < nbMessages; ++i) { auto m = msg.at(i); auto t = m.Type; if (modeGrouped) { if (t == SKGDocument::Warning) { m.Text = i18nc("Warning header", "Warning: %1", m.Text); } else if (t == SKGDocument::Error) { m.Text = i18nc("Error header", "Error: %1", m.Text); } else if (t == SKGDocument::Information) { m.Text = i18nc("Information header", "Information: %1", m.Text); } else if (t == SKGDocument::Positive) { m.Text = i18nc("Done header", "Done: %1", m.Text); } } if (modeGrouped || t == listGroups.at(indexGroup)) { // Same group if (!message.isEmpty()) { message += QStringLiteral("
"); } message += m.Text; } else { // Different group displayMessage(message, listGroups.at(indexGroup)); // Reset message message = m.Text; indexGroup++; } } if (nbMessages < 21 || !SKGServices::getEnvVariable(QStringLiteral("SKGTEST")).isEmpty()) { // Display a simple notification /*auto notify = new KNotification(KAboutData::applicationData().componentName() % "_info_event" , this); notify->setText(message); notify->sendEvent();*/ displayMessage(message, listGroups.at(indexGroup)); } else { // Too many message, display a warning panel KMessageBox::information(SKGMainPanel::getMainPanel(), message, i18nc("Noun", "Notification")); } } } } } void SKGMainPanel::changeEvent(QEvent* e) { KXmlGuiWindow::changeEvent(e); } QLabel* SKGMainPanel::statusNormalMessage() const { return d->m_kNormalMessage; } KMessageWidget* SKGMainPanel::getMessageWidget(const QString& iMessage, SKGDocument::MessageType iType, const QString& iAction, bool iAutoKillOnClick) { KMessageWidget* msg = nullptr; if (!iMessage.isEmpty()) { msg = new KMessageWidget(this); msg->setText(iMessage); msg->setIcon(SKGServices::fromTheme(iType == SKGDocument::Positive ? QStringLiteral("dialog-positive") : iType == SKGDocument::Information ? QStringLiteral("dialog-information") : iType == SKGDocument::Warning ? QStringLiteral("dialog-warning") : QStringLiteral("dialog-error"))); msg->setMessageType(static_cast(iType)); if (!iAction.isEmpty()) { QUrl url(iAction); if (url.scheme() == QStringLiteral("skg")) { QAction* action = SKGMainPanel::getMainPanel()->getGlobalAction(url.host(), false); QAction* act = nullptr; if (action != nullptr) { // This is an action act = new QAction(action->icon(), action->text(), SKGMainPanel::getMainPanel()); } else { // This is a default action act = new QAction(SKGServices::fromTheme(QStringLiteral("open")), i18nc("Verb", "Open ..."), SKGMainPanel::getMainPanel()); } act->setData(iAction); msg->addAction(act); connect(act, &QAction::triggered, this, [ = ] { openPage(QUrl(qobject_cast< QAction* >(sender())->data().toString()), true);}); if (iAutoKillOnClick) { connect(act, &QAction::triggered, msg, &KMessageWidget::deleteLater, Qt::QueuedConnection); } } } } return msg; } KMessageWidget* SKGMainPanel::displayMessage(const QString& iMessage, SKGDocument::MessageType iType, const QString& iAction) { // Create message widget KMessageWidget* msg = nullptr; if (!iMessage.isEmpty()) { msg = getMessageWidget(iMessage, iType, iAction, true); QTimer::singleShot(iType == SKGDocument::Positive ? 5000 : iType == SKGDocument::Information ? 10000 : 20000, Qt::CoarseTimer, msg, &KMessageWidget::deleteLater); msg->show(); d->m_mainLayout->insertWidget(qMax(d->m_mainLayout->indexOf(d->m_mainWidget) - 1, 0), msg); // Store message auto msg2 = getMessageWidget(iMessage, iType, iAction, false); auto* l = qobject_cast< QVBoxLayout* >(d->ui.kMessagesLayout->layout()); if (l != nullptr) { l->insertWidget(0, msg2); } } // Emit message // [Event/error] // [Event/neutral] // [Event/positive] auto notification = new KNotification(iType == SKGDocument::Error ? QStringLiteral("error") : (iType == SKGDocument::Positive ? QStringLiteral("positive") : (iType == SKGDocument::Warning ? QStringLiteral("negative") : QStringLiteral("neutral"))), this); notification->setText(iMessage); notification->sendEvent(); // Alert if (iType == SKGDocument::Error || iType == SKGDocument::Warning) { qApp->alert(this); } return msg; } KMessageWidget* SKGMainPanel::displayErrorMessage(const QString& iMessage) { QString msg = iMessage; if (msg.isEmpty()) { auto* act = qobject_cast< QAction* >(sender()); if (act != nullptr) { msg = act->data().toString(); } } return displayMessage(msg, SKGDocument::Error); } KMessageWidget* SKGMainPanel::displayErrorMessage(const SKGError& iError, bool iNotifyIfNoError) { return displayErrorMessage(iError, nullptr, iNotifyIfNoError); } KMessageWidget* SKGMainPanel::displayErrorMessage(const SKGError& iError, QAction* iAction, bool iNotifyIfNoError) { SKGTRACEINFUNC(1) KMessageWidget* msg = nullptr; SKGMainPanel* parent = SKGMainPanel::getMainPanel(); if (parent != nullptr) { if (iError) { // Get the message msg = parent->displayMessage(iError.getFullMessage(), SKGDocument::Error, iError.getAction()); // Add history action in case of if (iError.getHistoricalSize() != 0) { auto history = new QAction(i18nc("Noun", "History"), msg); history->setIcon(SKGServices::fromTheme(QStringLiteral("dialog-information"))); history->setData(iError.getFullMessageWithHistorical()); msg->addAction(history); connect(history, &QAction::triggered, parent, [ = ] { parent->displayErrorMessage();}); connect(history, &QAction::triggered, msg, &KMessageWidget::deleteLater, Qt::QueuedConnection); } // Add the additional action if (iAction != nullptr) { iAction->setParent(msg); msg->addAction(iAction); connect(iAction, &QAction::triggered, msg, &KMessageWidget::deleteLater, Qt::QueuedConnection); } } else { if (iNotifyIfNoError) { auto notification = new KNotification(QStringLiteral("positive"), parent); notification->setText(iError.getFullMessage()); notification->sendEvent(); } // Status bar QLabel* label = parent->statusNormalMessage(); QString message = iError.getMessage(); if ((label != nullptr) && !message.isEmpty()) { label->setText(message); } } } return msg; } void SKGMainPanel::onCancelCurrentAction() { SKGMainPanelPrivate::m_currentActionCanceled = true; } void SKGMainPanel::onQuitAction() { // Bug 2777697: To be sure that all page modifications are closed closeAllPages(true); // Bug 2777697: qApp->closeAllWindows(); } QString SKGMainPanel::getSaveFileName(const QString& iStartDir, const QString& iFilter, QWidget* iParent, QString* iCodec) { QString fileName; QString lastCodecUsed = QTextCodec::codecForLocale()->name(); KEncodingFileDialog::Result result = KEncodingFileDialog::getSaveUrlAndEncoding(lastCodecUsed, QUrl(iStartDir), iFilter, iParent); if (!result.URLs.isEmpty()) { fileName = result.URLs.at(0).toLocalFile(); } if (iCodec != nullptr) { *iCodec = result.encoding; } if (fileName.isEmpty()) { return QLatin1String(""); } QFile f(fileName); if (f.exists() && KMessageBox::warningContinueCancel(iParent, i18nc("Question", "File %1 already exists. Do you really want to overwrite it?", fileName), i18nc("Question", "Warning"), KGuiItem(i18nc("Verb", "Save"), SKGServices::fromTheme(QStringLiteral("document-save")))) != KMessageBox::Continue) { return QLatin1String(""); } return fileName; } void SKGMainPanel::fillWithDistinctValue( const QList& iWidgets, SKGDocument* iDoc, const QString& iTable, const QString& iAttribut, const QString& iWhereClause, bool iAddoperators) { SKGTRACEINFUNC(10) if (iDoc != nullptr) { { // Get list QStringList list; { SKGTRACEIN(10, "SKGMainPanel::fillWithDistinctValue-build list " % iTable % " " % iAttribut) iDoc->getDistinctValues(iTable, iAttribut, iWhereClause, list); if (!list.isEmpty() && !list.at(0).isEmpty()) { list.insert(0, QLatin1String("")); } // Sorting list { SKGTRACEIN(10, "SKGMainPanel::fillWithDistinctValue-build list sorting " % iTable % " " % iAttribut) // Correction bug 202341 vvv QCollator c; std::sort(list.begin(), list.end(), [&](const QString & a, const QString & b) { return c.compare(a, b) < 0; }); } // Add operator if (iAddoperators) { list.push_back('=' % i18nc("Key word to modify a string into a field", "capitalize")); list.push_back('=' % i18nc("Key word to modify a string into a field", "capwords")); list.push_back('=' % i18nc("Key word to modify a string into a field", "lower")); list.push_back('=' % i18nc("Key word to modify a string into a field", "trim")); list.push_back('=' % i18nc("Key word to modify a string into a field", "upper")); } } { SKGTRACEIN(10, "SKGMainPanel::fillWithDistinctValue-fill " % iTable % " " % iAttribut) SKGTRACEL(10) << "list.count()=" << list.count() << endl; for (auto w : qAsConst(iWidgets)) { auto comp = new QCompleter(list, w); if (comp != nullptr) { comp->setCaseSensitivity(Qt::CaseInsensitive); comp->setFilterMode(Qt::MatchContains); // Fill completion auto* kcmb = qobject_cast (w); if (kcmb != nullptr) { // Fill combo kcmb->clear(); kcmb->addItems(list); - if(kcmb->isEditable()) kcmb->setCompleter(comp); + if (kcmb->isEditable()) { + kcmb->setCompleter(comp); + } } else { auto* kline = qobject_cast (w); if (kline != nullptr) { kline->setClearButtonEnabled(true); kline->setCompleter(comp); } } } } } } } } SKGMainPanel* SKGMainPanel::getMainPanel() { return SKGMainPanelPrivate::m_mainPanel; } void SKGMainPanel::onZoomChanged() { SKGTabPage* toSave = currentPage(); if (toSave != nullptr) { toSave->setZoomPosition(d->m_zoomSelector->value()); d->m_zoomSelector->setValue(toSave->zoomPosition()); // In case of a limit is reached } } void SKGMainPanel::setMainWidget(QWidget* iWidget) { if (d->m_mainWidget == nullptr && d->m_mainLayout != nullptr && iWidget != nullptr) { d->m_mainWidget = iWidget; d->m_mainLayout->addWidget(d->m_mainWidget); // Show/hide main widget d->m_tabWidget->setVisible(d->m_tabWidget->count() != 0); if (d->m_mainWidget != nullptr) { d->m_mainWidget->setVisible(!d->m_tabWidget->isVisible()); } } } SKGTabWidget* SKGMainPanel::getTabWidget() const { return d->m_tabWidget; } void SKGMainPanel::onClearMessages() { QLayout* l = d->ui.kMessagesLayout->layout(); if (l != nullptr) { // Remove all item of the layout while (l->count() > 1) { QLayoutItem* child = l->takeAt(0); if (child != nullptr) { QWidget* w = child->widget(); delete w; delete child; } } } } void SKGMainPanel::onMigrateToSQLCipher() { SKGError err; SKGTRACEINFUNCRC(10, err) if (getDocument()->isFileModified()) { err = SKGError(ERR_ABORT, i18nc("An information message", "The document must be saved to be migrated."), QStringLiteral("skg://file_save")); } else { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Set parameters QString input = getDocument()->getCurrentFileName(); QString tmp = input % ".sqlcipher"; QString output = input % "_migrated.skg"; output = output.replace(QStringLiteral(".skg_migrated"), QStringLiteral("_migrated")); // Build argument QStringList arg; arg.push_back(QStringLiteral("--in")); arg.push_back(input); arg.push_back(QStringLiteral("--out")); arg.push_back(tmp); QString password = getDocument()->getPassword(); if (!password.isEmpty()) { arg.push_back(QStringLiteral("--param")); arg.push_back(QStringLiteral("password")); arg.push_back(QStringLiteral("--value")); arg.push_back(password); password = " --param password --value \"" % password % "\""; } // Conversion skg => sqlcipher QString cmd = "skroogeconvert --in \"" % input % "\" --out \"" % tmp % "\"" % password; int rc = QProcess::execute(QStringLiteral("skroogeconvert"), arg); if (rc != 0) { err.setReturnCode(ERR_FAIL).setMessage(i18nc("Error message", "The following command line failed with code %2:\n'%1'", cmd, rc)); } else { cmd = "skroogeconvert --in \"" % tmp % "\" --out \"" % output % "\"" % password; arg[1] = tmp; arg[3] = output; rc = QProcess::execute(QStringLiteral("skroogeconvert"), arg); if (rc != 0) { err.setReturnCode(ERR_FAIL).setMessage(i18nc("Error message", "The following command line failed with code %2:\n'%1'", cmd, rc)); } else { 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); notify(); } } QFile(tmp).remove(); QApplication::restoreOverrideCursor(); } // Display error SKGMainPanel::displayErrorMessage(err); } QString SKGMainPanel::dateToString(QDate iDate) { switch (skgbasegui_settings::date_format()) { case 0: return QLocale().toString(iDate, QLocale::ShortFormat); case 1: return QLocale().toString(iDate, QLocale::LongFormat); case 3: return KFormat().formatRelativeDate(iDate, QLocale::LongFormat); case 4: return iDate.toString(Qt::ISODate); case 2: default: return KFormat().formatRelativeDate(iDate, QLocale::ShortFormat); } }