Commit 09dc3d44 authored by Nikita Sirgienko's avatar Nikita Sirgienko
Browse files

[GSoC 2020] Increase Cantor Plugins Performance

Now all panels belongs to CantorShell instead of Cantor Part, so now there is only one instance of each Panel in Cantor.
The changing of Panels content during Worksheets changes will be done via new methods: saveState, restoreState.
parent 94e968ff
Pipeline #28016 canceled with stage
...@@ -48,8 +48,9 @@ ...@@ -48,8 +48,9 @@
#include "settings.h" #include "settings.h"
#include "ui_settings.h" #include "ui_settings.h"
#include "backendchoosedialog.h" #include "backendchoosedialog.h"
#include <QMetaObject>
CantorShell::CantorShell() : KParts::MainWindow(), m_part(nullptr) CantorShell::CantorShell() : KParts::MainWindow(), m_part(nullptr), m_panelHandler(nullptr)
{ {
// set the shell's ui resource file // set the shell's ui resource file
setXMLFile(QLatin1String("cantor_shell.rc")); setXMLFile(QLatin1String("cantor_shell.rc"));
...@@ -75,6 +76,8 @@ CantorShell::CantorShell() : KParts::MainWindow(), m_part(nullptr) ...@@ -75,6 +76,8 @@ CantorShell::CantorShell() : KParts::MainWindow(), m_part(nullptr)
setDockOptions(QMainWindow::AnimatedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::VerticalTabs); setDockOptions(QMainWindow::AnimatedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::VerticalTabs);
initPanels();
updateNewSubmenu(); updateNewSubmenu();
} }
...@@ -358,7 +361,7 @@ void CantorShell::addWorksheet(const QString& backendName) ...@@ -358,7 +361,7 @@ void CantorShell::addWorksheet(const QString& backendName)
{ {
connect(part, SIGNAL(setCaption(QString,QIcon)), this, SLOT(setTabCaption(QString,QIcon))); connect(part, SIGNAL(setCaption(QString,QIcon)), this, SLOT(setTabCaption(QString,QIcon)));
connect(part, SIGNAL(worksheetSave(QUrl)), this, SLOT(onWorksheetSave(QUrl))); connect(part, SIGNAL(worksheetSave(QUrl)), this, SLOT(onWorksheetSave(QUrl)));
connect(part, SIGNAL(requestOpenWorksheet(QUrl)), this, SLOT(load(QUrl))); connect(part, SIGNAL(showHelp(QString)), this, SIGNAL(showHelp(QString)));
m_parts.append(part); m_parts.append(part);
if (backend) // If backend empty (loading worksheet from file), then we connect to signal and wait if (backend) // If backend empty (loading worksheet from file), then we connect to signal and wait
m_parts2Backends[part] = backend->id(); m_parts2Backends[part] = backend->id();
...@@ -396,11 +399,7 @@ void CantorShell::addWorksheet(const QString& backendName) ...@@ -396,11 +399,7 @@ void CantorShell::addWorksheet(const QString& backendName)
void CantorShell::activateWorksheet(int index) void CantorShell::activateWorksheet(int index)
{ {
QObject* pluginHandler=m_part->findChild<QObject*>(QLatin1String("PanelPluginHandler")); // Save part panels states before change worksheet
if (pluginHandler)
disconnect(pluginHandler,SIGNAL(pluginsChanged()), this, SLOT(updatePanel()));
// Save part state before change worksheet
if (m_part) if (m_part)
{ {
QStringList visiblePanelNames; QStringList visiblePanelNames;
...@@ -410,6 +409,16 @@ void CantorShell::activateWorksheet(int index) ...@@ -410,6 +409,16 @@ void CantorShell::activateWorksheet(int index)
visiblePanelNames << doc->objectName(); visiblePanelNames << doc->objectName();
} }
m_pluginsVisibility[m_part] = visiblePanelNames; m_pluginsVisibility[m_part] = visiblePanelNames;
Cantor::WorksheetAccessInterface* wa=m_part->findChild<Cantor::WorksheetAccessInterface*>(Cantor::WorksheetAccessInterface::Name);
assert(wa);
PanelStates states;
QList<Cantor::PanelPlugin*> plugins=m_panelHandler.plugins(wa->session());
for(Cantor::PanelPlugin* plugin : plugins)
{
states.insert(plugin->name(), plugin->saveState());
}
m_pluginsStates[m_part] = states;
} }
m_part=findPart(m_tabWidget->widget(index)); m_part=findPart(m_tabWidget->widget(index));
...@@ -418,8 +427,6 @@ void CantorShell::activateWorksheet(int index) ...@@ -418,8 +427,6 @@ void CantorShell::activateWorksheet(int index)
createGUI(m_part); createGUI(m_part);
updateWindowTitle(m_part->url().fileName()); updateWindowTitle(m_part->url().fileName());
QObject* pluginHandler=m_part->findChild<QObject*>(QLatin1String("PanelPluginHandler"));
connect(pluginHandler, SIGNAL(pluginsChanged()), this, SLOT(updatePanel()));
updatePanel(); updatePanel();
} }
else else
...@@ -482,6 +489,7 @@ void CantorShell::closeTab(int index) ...@@ -482,6 +489,7 @@ void CantorShell::closeTab(int index)
m_tabWidget->removeTab(index); m_tabWidget->removeTab(index);
bool isCurrectPartClosed = m_part ? widget == m_part->widget() : false;
if(widget->objectName()==QLatin1String("ErrorMessage")) if(widget->objectName()==QLatin1String("ErrorMessage"))
{ {
widget->deleteLater(); widget->deleteLater();
...@@ -495,12 +503,15 @@ void CantorShell::closeTab(int index) ...@@ -495,12 +503,15 @@ void CantorShell::closeTab(int index)
m_parts.removeAll(part); m_parts.removeAll(part);
m_pluginsVisibility.remove(part); m_pluginsVisibility.remove(part);
m_parts2Backends.remove(part); m_parts2Backends.remove(part);
m_pluginsStates.remove(part);
delete part; delete part;
} }
} }
if (m_tabWidget->count() == 0) if (m_tabWidget->count() == 0)
setCaption(QString()); setCaption(QString());
if (isCurrectPartClosed || m_part == nullptr)
updatePanel(); updatePanel();
} }
...@@ -645,35 +656,46 @@ KParts::ReadWritePart* CantorShell::findPart(QWidget* widget) ...@@ -645,35 +656,46 @@ KParts::ReadWritePart* CantorShell::findPart(QWidget* widget)
return nullptr; return nullptr;
} }
void CantorShell::updatePanel() void CantorShell::initPanels()
{ {
unplugActionList(QLatin1String("view_show_panel_list")); m_panelHandler.loadPlugins();
//remove all of the previous panels (but do not delete the widgets) QList<Cantor::PanelPlugin*> plugins = m_panelHandler.allPlugins();
foreach(QDockWidget* dock, m_panels) foreach(Cantor::PanelPlugin* plugin, plugins)
{ {
QWidget* widget=dock->widget(); if(plugin==nullptr)
if(widget!=nullptr)
{ {
widget->setParent(this); qDebug()<<"somethings wrong";
widget->hide(); continue;
}
dock->deleteLater();
} }
m_panels.clear();
QList<QAction*> panelActions; qDebug()<<"adding panel for "<<plugin->name();
plugin->setParentWidget(this);
plugin->connectToShell(this);
QDockWidget* docker=new QDockWidget(plugin->name(), this);
docker->setObjectName(plugin->name());
docker->setWidget(plugin->widget());
addDockWidget ( Qt::RightDockWidgetArea, docker );
docker->hide();
connect(plugin, &Cantor::PanelPlugin::visibilityRequested, this, &CantorShell::pluginVisibilityRequested);
connect(plugin, &Cantor::PanelPlugin::requestRunCommand, this, &CantorShell::pluginCommandRunRequested);
m_panels.append(docker);
Cantor::PanelPluginHandler* handler=m_part->findChild<Cantor::PanelPluginHandler*>(QLatin1String("PanelPluginHandler"));
if(!handler)
{
qDebug()<<"no PanelPluginHandle found for this part";
return;
} }
}
QDockWidget* last=nullptr;
bool isNewWorksheet = !m_pluginsVisibility.contains(m_part);
void CantorShell::updatePanel()
{
unplugActionList(QLatin1String("view_show_panel_list"));
QList<QAction*> panelActions;
bool isNewWorksheet = !m_pluginsVisibility.contains(m_part);
if (isNewWorksheet) if (isNewWorksheet)
{ {
KConfigGroup panelStatusGroup(KSharedConfig::openConfig(), QLatin1String("PanelsStatus")); KConfigGroup panelStatusGroup(KSharedConfig::openConfig(), QLatin1String("PanelsStatus"));
...@@ -685,8 +707,17 @@ void CantorShell::updatePanel() ...@@ -685,8 +707,17 @@ void CantorShell::updatePanel()
} }
} }
QList<Cantor::PanelPlugin*> plugins=handler->plugins(); Cantor::WorksheetAccessInterface* wa = nullptr;
foreach(Cantor::PanelPlugin* plugin, plugins) if (m_part)
wa = m_part->findChild<Cantor::WorksheetAccessInterface*>(Cantor::WorksheetAccessInterface::Name);
// Worksheet interface can be missing on m_part clossing (and m_part on this moment can be nullptr)
QList<Cantor::PanelPlugin*> plugins;
if (wa)
{
QDockWidget* last=nullptr;
plugins = m_panelHandler.plugins(wa->session());
for(Cantor::PanelPlugin* plugin : plugins)
{ {
if(plugin==nullptr) if(plugin==nullptr)
{ {
...@@ -695,41 +726,68 @@ void CantorShell::updatePanel() ...@@ -695,41 +726,68 @@ void CantorShell::updatePanel()
} }
qDebug()<<"adding panel for "<<plugin->name(); qDebug()<<"adding panel for "<<plugin->name();
plugin->setParentWidget(this);
QDockWidget* docker=new QDockWidget(plugin->name(), this); if (m_pluginsStates.contains(m_part))
docker->setObjectName(plugin->name()); plugin->restoreState(m_pluginsStates[m_part][plugin->name()]);
docker->setWidget(plugin->widget()); else
addDockWidget ( Qt::RightDockWidgetArea, docker ); {
Cantor::PanelPlugin::State initState;
initState.session = wa->session();
plugin->restoreState(initState);
}
QDockWidget* foundDocker = nullptr;
for (QDockWidget* docker : m_panels)
if (docker->objectName() == plugin->name())
{
foundDocker = docker;
break;
}
if (!foundDocker)
{
qDebug() << "something wrong: can't find panel for plugin \"" << plugin->name() << "\"";
continue;
}
// Set visibility for dock from saved info // Set visibility for dock from saved info
if (isNewWorksheet) if (isNewWorksheet)
{ {
if (plugin->showOnStartup()) if (plugin->showOnStartup())
docker->show(); foundDocker->show();
else else
docker->hide(); foundDocker->hide();
} }
else else
{ {
if (m_pluginsVisibility[m_part].contains(plugin->name())) if (m_pluginsVisibility[m_part].contains(plugin->name()))
docker->show(); foundDocker->show();
else else
docker->hide(); foundDocker->hide();
} }
if(last!=nullptr) if(last!=nullptr)
tabifyDockWidget(last, docker); tabifyDockWidget(last, foundDocker);
last=docker; last = foundDocker;
connect(plugin, &Cantor::PanelPlugin::visibilityRequested, this, &CantorShell::pluginVisibilityRequested);
m_panels.append(docker);
//Create the action to show/hide this panel //Create the action to show/hide this panel
panelActions<<docker->toggleViewAction(); panelActions<<foundDocker->toggleViewAction();
} }
}
// Hide plugins, which don't supported on current session
QList<Cantor::PanelPlugin*> allPlugins=m_panelHandler.allPlugins();
for(Cantor::PanelPlugin* plugin : allPlugins)
{
if (plugins.indexOf(plugin) == -1)
for (QDockWidget* docker : m_panels)
if (docker->objectName() == plugin->name())
{
docker->hide();
break;
}
}
plugActionList(QLatin1String("view_show_panel_list"), panelActions); plugActionList(QLatin1String("view_show_panel_list"), panelActions);
...@@ -769,7 +827,7 @@ void CantorShell::pluginVisibilityRequested() ...@@ -769,7 +827,7 @@ void CantorShell::pluginVisibilityRequested()
Cantor::PanelPlugin* plugin = static_cast<Cantor::PanelPlugin*>(sender()); Cantor::PanelPlugin* plugin = static_cast<Cantor::PanelPlugin*>(sender());
for (QDockWidget* docker: m_panels) for (QDockWidget* docker: m_panels)
{ {
if (plugin->name() == docker->windowTitle()) if (plugin->name() == docker->objectName())
{ {
if (docker->isHidden()) if (docker->isHidden())
docker->show(); docker->show();
...@@ -829,3 +887,11 @@ void CantorShell::updateBackendForPart(const QString& backend) ...@@ -829,3 +887,11 @@ void CantorShell::updateBackendForPart(const QString& backend)
} }
} }
} }
void CantorShell::pluginCommandRunRequested(const QString& cmd)
{
if (m_part)
{
QMetaObject::invokeMethod(m_part, "runCommand", Qt::QueuedConnection, Q_ARG(QString, cmd));
}
}
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#include <QStringList> #include <QStringList>
#include <QMap> #include <QMap>
#include "lib/panelpluginhandler.h"
#include "lib/panelplugin.h"
class QTabWidget; class QTabWidget;
class KTextEdit; class KTextEdit;
class KRecentFilesAction; class KRecentFilesAction;
...@@ -40,6 +43,8 @@ namespace KParts{ ...@@ -40,6 +43,8 @@ namespace KParts{
class ReadWritePart; class ReadWritePart;
} }
using PanelStates = QMap<QString, Cantor::PanelPlugin::State>;
/** /**
* This is the application "Shell". It has a menubar, toolbar, and * This is the application "Shell". It has a menubar, toolbar, and
* statusbar but relies on the "Part" to do all the real work. * statusbar but relies on the "Part" to do all the real work.
...@@ -75,6 +80,9 @@ protected: ...@@ -75,6 +80,9 @@ protected:
*/ */
void readProperties(const KConfigGroup &) override; void readProperties(const KConfigGroup &) override;
Q_SIGNALS:
void showHelp(QString);
public Q_SLOTS: public Q_SLOTS:
void addWorksheet(const QString& backendName); void addWorksheet(const QString& backendName);
/// Use this method/slot to load whatever file/URL you have /// Use this method/slot to load whatever file/URL you have
...@@ -97,10 +105,12 @@ private Q_SLOTS: ...@@ -97,10 +105,12 @@ private Q_SLOTS:
void downloadExamples(); void downloadExamples();
void openExample(); void openExample();
void initPanels();
void updatePanel(); void updatePanel();
void updateNewSubmenu(); void updateNewSubmenu();
void pluginVisibilityRequested(); void pluginVisibilityRequested();
void pluginCommandRunRequested(const QString& cmd);
private: private:
void setupActions(); void setupActions();
...@@ -113,6 +123,7 @@ private: ...@@ -113,6 +123,7 @@ private:
private: private:
QMap<KParts::ReadWritePart*, QStringList> m_pluginsVisibility; QMap<KParts::ReadWritePart*, QStringList> m_pluginsVisibility;
QMap<KParts::ReadWritePart*, PanelStates> m_pluginsStates;
QList<KParts::ReadWritePart *> m_parts; QList<KParts::ReadWritePart *> m_parts;
QMap<KParts::ReadWritePart*, QString> m_parts2Backends; QMap<KParts::ReadWritePart*, QString> m_parts2Backends;
KParts::ReadWritePart* m_part; KParts::ReadWritePart* m_part;
...@@ -122,6 +133,8 @@ private: ...@@ -122,6 +133,8 @@ private:
QDockWidget* m_helpDocker; QDockWidget* m_helpDocker;
KRecentFilesAction* m_recentProjectsAction; KRecentFilesAction* m_recentProjectsAction;
Cantor::PanelPluginHandler m_panelHandler;
// For better UX: set previous used filter in "Open" action as default filter // For better UX: set previous used filter in "Open" action as default filter
QString m_previousFilter; QString m_previousFilter;
}; };
......
...@@ -110,7 +110,6 @@ class WorksheetAccessInterfaceImpl : public Cantor::WorksheetAccessInterface ...@@ -110,7 +110,6 @@ class WorksheetAccessInterfaceImpl : public Cantor::WorksheetAccessInterface
CantorPart::CantorPart( QWidget *parentWidget, QObject *parent, const QVariantList & args ): KParts::ReadWritePart(parent), CantorPart::CantorPart( QWidget *parentWidget, QObject *parent, const QVariantList & args ): KParts::ReadWritePart(parent),
m_searchBar(nullptr), m_searchBar(nullptr),
m_panelHandler(new Cantor::PanelPluginHandler(this)),
m_initProgressDlg(nullptr), m_initProgressDlg(nullptr),
m_showProgressDlg(true), m_showProgressDlg(true),
m_currectZoomAction(nullptr), m_currectZoomAction(nullptr),
...@@ -118,8 +117,6 @@ CantorPart::CantorPart( QWidget *parentWidget, QObject *parent, const QVariantLi ...@@ -118,8 +117,6 @@ CantorPart::CantorPart( QWidget *parentWidget, QObject *parent, const QVariantLi
m_statusBarBlocked(false), m_statusBarBlocked(false),
m_sessionStatusCounter(0) m_sessionStatusCounter(0)
{ {
connect(m_panelHandler, &Cantor::PanelPluginHandler::pluginsChanged, this, &CantorPart::pluginsChanged);
QString backendName; QString backendName;
if(!args.isEmpty()) if(!args.isEmpty())
backendName = args.first().toString(); backendName = args.first().toString();
...@@ -693,7 +690,6 @@ void CantorPart::initialized() ...@@ -693,7 +690,6 @@ void CantorPart::initialized()
connect(m_worksheet->session(), &Cantor::Session::error, this, &CantorPart::showSessionError); connect(m_worksheet->session(), &Cantor::Session::error, this, &CantorPart::showSessionError);
loadAssistants(); loadAssistants();
m_panelHandler->setSession(m_worksheet->session());
adjustGuiToSession(); adjustGuiToSession();
// Don't set modification flag, if we add command entry in empty worksheet // Don't set modification flag, if we add command entry in empty worksheet
...@@ -773,12 +769,6 @@ void CantorPart::updateCaption() ...@@ -773,12 +769,6 @@ void CantorPart::updateCaption()
emit setCaption(filename+QLatin1Char(' ') + i18n("[read-only]"), QIcon()); emit setCaption(filename+QLatin1Char(' ') + i18n("[read-only]"), QIcon());
} }
void CantorPart::pluginsChanged()
{
for (auto* plugin : m_panelHandler->plugins())
connect(plugin, &Cantor::PanelPlugin::requestRunCommand, this, &CantorPart::runCommand);
}
void CantorPart::loadAssistants() void CantorPart::loadAssistants()
{ {
qDebug()<<"loading assistants..."; qDebug()<<"loading assistants...";
......
...@@ -84,7 +84,6 @@ Q_SIGNALS: ...@@ -84,7 +84,6 @@ Q_SIGNALS:
void setCaption(const QString& caption, const QIcon& icon); void setCaption(const QString& caption, const QIcon& icon);
void showHelp(const QString& help); void showHelp(const QString& help);
void worksheetSave(const QUrl& url); void worksheetSave(const QUrl& url);
void requestOpenWorksheet(const QUrl& url);
void setBackendName(const QString& name); void setBackendName(const QString& name);
public Q_SLOTS: public Q_SLOTS:
...@@ -132,7 +131,6 @@ protected Q_SLOTS: ...@@ -132,7 +131,6 @@ protected Q_SLOTS:
void worksheetSessionLoginDone(); void worksheetSessionLoginDone();
void initialized(); void initialized();
void pluginsChanged();
void runCommand(const QString& value); void runCommand(const QString& value);
void runAssistant(); void runAssistant();
...@@ -168,7 +166,6 @@ private: ...@@ -168,7 +166,6 @@ private:
WorksheetView *m_worksheetview; WorksheetView *m_worksheetview;
SearchBar *m_searchBar; SearchBar *m_searchBar;
QPointer<ScriptEditorWidget> m_scriptEditor; QPointer<ScriptEditorWidget> m_scriptEditor;
Cantor::PanelPluginHandler* m_panelHandler;
QProgressDialog* m_initProgressDlg; QProgressDialog* m_initProgressDlg;
bool m_showProgressDlg; bool m_showProgressDlg;
......
...@@ -75,18 +75,24 @@ QString PanelPlugin::name() ...@@ -75,18 +75,24 @@ QString PanelPlugin::name()
return d->name; return d->name;
} }
Session* PanelPlugin::session() Cantor::PanelPlugin::State Cantor::PanelPlugin::saveState()
{ {
return d->session; Cantor::PanelPlugin::State state;
state.session = d->session;
return state;
} }
void PanelPlugin::setSession(Session* session) void Cantor::PanelPlugin::restoreState(const Cantor::PanelPlugin::State& state)
{ {
d->session=session; d->session = state.session;
onSessionChanged(); }
Cantor::Session * Cantor::PanelPlugin::session()
{
return d->session;
} }
void PanelPlugin::onSessionChanged() void Cantor::PanelPlugin::connectToShell(QObject* /* cantorShell */)
{ {
} }
......
...@@ -40,6 +40,12 @@ class CANTOR_EXPORT PanelPlugin : public QObject ...@@ -40,6 +40,12 @@ class CANTOR_EXPORT PanelPlugin : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
struct State {
Session* session{nullptr};
QVector<QVariant> inners;
};
/** /**
* Create a new PanelPlugin * Create a new PanelPlugin
* @param parent the parent Object @see QObject * @param parent the parent Object @see QObject
...@@ -91,14 +97,21 @@ class CANTOR_EXPORT PanelPlugin : public QObject ...@@ -91,14 +97,21 @@ class CANTOR_EXPORT PanelPlugin : public QObject
QWidget* parentWidget(); QWidget* parentWidget();
/** /**
* sets the session this plugin operates on * Save state of panel to storable form
*
**/ **/
void setSession(Session* session); virtual State saveState();
/** /**
* returns the session * Restore state
* Can contains only session - this is init state from Cantor shell