Commit 463986f6 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Refactor KoResourceServer to allow storing shared pointers

Now KoResourceServer has a second template parameter that defines
the policy which should be used for storing a resource. There are
to predefined policies:

* PointerStroragePolicy --- usual pointers with ownership over
                            the resource.
* SharedPointerStroragePolicy --- shared pointers. The server does no
                                  extra handling for the lifetime of
                                  the resource.

Use the former for usual resources and the latter for shared pointer based
ones.
parent 311d6af5
......@@ -37,60 +37,14 @@
#include "kis_png_brush.h"
#include "kis_svg_brush.h"
class BrushResourceServer : public KoResourceServer<KisBrush>, public KoResourceServerObserver<KisBrush>
class BrushResourceServer : public KisBrushResourceServer
{
public:
BrushResourceServer()
: KoResourceServer<KisBrush>("kis_brushes", "*.gbr:*.gih:*.abr:*.png:*.svg", false)
: KisBrushResourceServer("kis_brushes", "*.gbr:*.gih:*.abr:*.png:*.svg")
{
addObserver(this, true);
}
virtual ~BrushResourceServer()
{
destroyTagStorage();
foreach(KisBrush* brush, m_brushes) {
if (!brush->deref()) {
delete brush;
}
m_brushes.removeAll(brush);
}
}
virtual void unsetResourceServer()
{
//...
}
virtual void resourceAdded(KisBrush* brush) {
// Hack: This prevents the deletion of brushes in the resource server
// Brushes outside the server use shared pointer, but not inside the server
brush->ref();
m_brushes.append(brush);
}
///Reimplemented
virtual void removingResource(KisBrush* brush) {
if (!brush->deref()) {
delete brush;
}
m_brushes.removeAll(brush);
}
virtual void resourceChanged(KisBrush* resource) {
Q_UNUSED(resource);
}
virtual void syncTaggedResourceView() {}
virtual void syncTagAddition(const QString& tag) {
Q_UNUSED(tag);
}
virtual void syncTagRemoval(const QString& tag) {
Q_UNUSED(tag);
}
///Reimplemented
......@@ -105,21 +59,21 @@ public:
if (fileCreation) {
QFile::copy(filename, saveLocation() + fi.fileName());
}
QList<KisBrush*> collectionResources = createResources(filename);
foreach(KisBrush * brush, collectionResources) {
QList<KisBrushSP> collectionResources = createResources(filename);
foreach(KisBrushSP brush, collectionResources) {
addResource(brush);
}
}
else {
KoResourceServer<KisBrush>::importResourceFile(filename, fileCreation);
KisBrushResourceServer::importResourceFile(filename, fileCreation);
}
}
private:
///Reimplemented
virtual QList<KisBrush*> createResources(const QString & filename) {
QList<KisBrush*> brushes;
virtual QList<KisBrushSP> createResources(const QString & filename) {
QList<KisBrushSP> brushes;
QString fileExtension = QFileInfo(filename).suffix().toLower();
if (fileExtension == "abr") {
......@@ -136,11 +90,11 @@ private:
}
///Reimplemented
virtual KisBrush* createResource(const QString & filename) {
virtual KisBrushSP createResource(const QString & filename) {
QString fileExtension = QFileInfo(filename).suffix().toLower();
KisBrush* brush = 0;
KisBrushSP brush;
if (fileExtension == "gbr") {
brush = new KisGbrBrush(filename);
......@@ -156,8 +110,6 @@ private:
}
return brush;
}
QList<KisBrush*> m_brushes;
};
KisBrushServer::KisBrushServer()
......@@ -189,7 +141,7 @@ KisBrushServer* KisBrushServer::instance()
}
KoResourceServer<KisBrush>* KisBrushServer::brushServer()
KisBrushResourceServer* KisBrushServer::brushServer()
{
m_brushThread->barrier();
return m_brushServer;
......
......@@ -23,6 +23,7 @@
#include <QList>
#include <KoResourceServer.h>
#include <KoResourceServerAdapter.h>
#include "krita_export.h"
#include "kis_brush.h"
......@@ -30,6 +31,9 @@
class KoResource;
class KoResourceLoaderThread;
typedef KoResourceServer<KisBrush, SharedPointerStroragePolicy<KisBrushSP> > KisBrushResourceServer;
typedef KoResourceServerAdapter<KisBrush, SharedPointerStroragePolicy<KisBrushSP> > KisBrushResourceServerAdapter;
/**
*
*/
......@@ -41,7 +45,7 @@ class BRUSH_EXPORT KisBrushServer : public QObject
public:
virtual ~KisBrushServer();
KoResourceServer<KisBrush>* brushServer();
KisBrushResourceServer* brushServer();
static KisBrushServer* instance();
......@@ -54,7 +58,7 @@ private:
KisBrushServer(const KisBrushServer&);
KisBrushServer operator=(const KisBrushServer&);
KoResourceServer<KisBrush>* m_brushServer;
KisBrushResourceServer* m_brushServer;
private:
KoResourceLoaderThread *m_brushThread;
......
......@@ -35,7 +35,7 @@ QString KisPredefinedBrushFactory::id() const
KisBrushSP KisPredefinedBrushFactory::getOrCreateBrush(const QDomElement& brushDefinition)
{
KoResourceServer<KisBrush> *rServer = KisBrushServer::instance()->brushServer();
KisBrushResourceServer *rServer = KisBrushServer::instance()->brushServer();
QString brushFileName = brushDefinition.attribute("filename", "");
KisBrushSP brush = rServer->resourceByFilename(brushFileName);
......
......@@ -121,8 +121,8 @@ KisBrushChooser::KisBrushChooser(QWidget *parent, const char *name)
m_lbName = new QLabel(this);
KoResourceServer<KisBrush>* rServer = KisBrushServer::instance()->brushServer();
QSharedPointer<KoResourceServerAdapter<KisBrush> > adapter(new KoResourceServerAdapter<KisBrush>(rServer));
KisBrushResourceServer* rServer = KisBrushServer::instance()->brushServer();
QSharedPointer<KisBrushResourceServerAdapter> adapter(new KisBrushResourceServerAdapter(rServer));
m_itemChooser = new KoResourceItemChooser(adapter, this);
QString knsrcFile = "kritabrushes.knsrc";
m_itemChooser->setKnsrcFile(knsrcFile);
......
......@@ -46,8 +46,8 @@ KisClipboardBrushWidget::KisClipboardBrushWidget(QWidget *parent, const QString
spacingSlider->setRange(0.0, 1.0, 2);
spacingSlider->setValue(0.25);
KoResourceServer<KisBrush>* rServer = KisBrushServer::instance()->brushServer();
m_rServerAdapter = QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KisBrush>(rServer));
KisBrushResourceServer* rServer = KisBrushServer::instance()->brushServer();
m_rServerAdapter = QSharedPointer<KisBrushResourceServerAdapter>(new KisBrushResourceServerAdapter(rServer));
m_brush = 0;
m_brushCreated = false;
......
......@@ -55,8 +55,8 @@ KisCustomBrushWidget::KisCustomBrushWidget(QWidget *parent, const QString& capti
preview->setScaledContents(true);
preview->setFixedSize(preview->size());
KoResourceServer<KisBrush>* rServer = KisBrushServer::instance()->brushServer();
m_rServerAdapter = QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KisBrush>(rServer));
KisBrushResourceServer* rServer = KisBrushServer::instance()->brushServer();
m_rServerAdapter = QSharedPointer<KisBrushResourceServerAdapter>(new KisBrushResourceServerAdapter(rServer));
m_brush = 0;
m_brushCreated = false;
......
......@@ -252,8 +252,8 @@ void KoDlgCreateBundle::resourceTypeSelected(int idx)
m_ui->tableSelected->clear();
if (resourceType == "brushes") {
KoResourceServer<KisBrush>* server = KisBrushServer::instance()->brushServer();
foreach(KoResource *res, server->resources()) {
KisBrushResourceServer *server = KisBrushServer::instance()->brushServer();
foreach(KisBrushSP res, server->resources()) {
QListWidgetItem *item = new QListWidgetItem(imageToIcon(res->image()), res->name());
item->setData(Qt::UserRole, res->shortFilename());
......
......@@ -255,10 +255,11 @@ bool KoResourceBundle::save()
}
}
else if (resType == "kis_brushes") {
KoResourceServer<KisBrush>* brushServer = KisBrushServer::instance()->brushServer();
KisBrushResourceServer* brushServer = KisBrushServer::instance()->brushServer();
foreach(const KoXmlResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) {
KoResource *res = brushServer->resourceByMD5(ref.md5sum);
if (!res) res = brushServer->resourceByFilename(QFileInfo(ref.resourcePath).completeBaseName());
KisBrushSP brush = brushServer->resourceByMD5(ref.md5sum);
if (!brush) brush = brushServer->resourceByFilename(QFileInfo(ref.resourcePath).completeBaseName());
KoResource *res = brush.data();
saveResourceToStore(res, store.data(), "brushes");
}
}
......@@ -394,9 +395,9 @@ void KoResourceBundle::install()
}
}
else if (resType == "kis_brushes") {
KoResourceServer<KisBrush>* brushServer = KisBrushServer::instance()->brushServer();
KisBrushResourceServer *brushServer = KisBrushServer::instance()->brushServer();
foreach(const KoXmlResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) {
KisBrush *res = brushServer->createResource(ref.resourcePath);
KisBrushSP res = brushServer->createResource(ref.resourcePath);
if (!resourceStore->open(ref.resourcePath)) {
qWarning() << "Failed to open" << ref.resourcePath << "from bundle" << filename();
}
......@@ -405,9 +406,9 @@ void KoResourceBundle::install()
}
brushServer->addResource(res, false);
foreach(const QString &tag, ref.tagList) {
brushServer->addTag(res, tag);
brushServer->addTag(res.data(), tag);
}
brushServer->addTag(res, name());
brushServer->addTag(res.data(), name());
}
}
else if (resType == "ko_palettes") {
......
......@@ -384,7 +384,7 @@ void KoResourceManagerControl::filterResourceTypes(int index)
case 0:
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KoAbstractGradient>(KoResourceServerProvider::instance()->gradientServer())));
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KoPattern>(KoResourceServerProvider::instance()->patternServer())));
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KisBrush>(KisBrushServer::instance()->brushServer())));
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KisBrushResourceServerAdapter(KisBrushServer::instance()->brushServer())));
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KoColorSet>(KoResourceServerProvider::instance()->paletteServer())));
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KisPaintOpPreset>(KisResourceServerProvider::instance()->paintOpPresetServer())));
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KisWorkspaceResource>(KisResourceServerProvider::instance()->workspaceServer())));
......@@ -398,7 +398,7 @@ void KoResourceManagerControl::filterResourceTypes(int index)
m_modelList.append(new KoResourceTableModel(list, KoResourceTableModel::Installed));
break;
case 2:
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KoResourceServerAdapter<KisBrush>(KisBrushServer::instance()->brushServer())));
list.append(QSharedPointer<KoAbstractResourceServerAdapter>(new KisBrushResourceServerAdapter(KisBrushServer::instance()->brushServer())));
m_modelList.append(new KoResourceTableModel(list, KoResourceTableModel::Undefined));
m_modelList.append(new KoResourceTableModel(list, KoResourceTableModel::Undefined));
break;
......
......@@ -97,7 +97,7 @@ public:
workspaceServer = KisResourceServerProvider::instance()->workspaceServer();
}
KoResourceServer<KisBrush>* brushServer;
KisBrushResourceServer* brushServer;
KoResourceServer<KisPaintOpPreset>* paintopServer;
KoResourceServer<KoAbstractGradient>* gradientServer;
KoResourceServer<KoResourceBundle> *bundleServer;
......@@ -262,7 +262,7 @@ void ResourceManager::slotCreateBundle()
QStringList res = dlgCreateBundle.selectedBrushes();
foreach(const QString &r, res) {
KoResource *res = d->brushServer->resourceByFilename(r);
KoResource *res = d->brushServer->resourceByFilename(r).data();
newBundle->addResource("kis_brushes", res->filename(), d->brushServer->tagObject()->assignedTagsList(res), res->md5());
}
......
......@@ -103,12 +103,12 @@ void KoResourceBundleTest::testLoadSave()
bundle.addResource(patternServer->type(), pattern->filename(), patternServer->tagObject()->assignedTagsList(pattern), pattern->md5());
}
KoResourceServer<KisBrush>* brushServer = KisBrushServer::instance()->brushServer();
KisBrushResourceServer* brushServer = KisBrushServer::instance()->brushServer();
QVERIFY(brushServer->resoureCount() > 0);
foreach(KisBrush* brush, brushServer->resources()) {
brushServer->addTag(brush, QString("testtag: %1").arg(tagCount));
foreach(KisBrushSP brush, brushServer->resources()) {
brushServer->addTag(brush.data(), QString("testtag: %1").arg(tagCount));
tagCount++;
bundle.addResource(brushServer->type(), brush->filename(), brushServer->tagObject()->assignedTagsList(brush), brush->md5());
bundle.addResource(brushServer->type(), brush->filename(), brushServer->tagObject()->assignedTagsList(brush.data()), brush->md5());
}
......
......@@ -41,6 +41,7 @@
#include <QTemporaryFile>
#include <QDomDocument>
#include "KoResource.h"
#include "KoResourceServerPolicies.h"
#include "KoResourceServerObserver.h"
#include "KoResourceTagStore.h"
......@@ -109,15 +110,33 @@ protected:
};
/**
* KoResourceServer manages the resources of one type. It stores, loads and saves the resources.
* To keep track of changes the server can be observed with a KoResourceServerObserver
* KoResourceServer manages the resources of one type. It stores,
* loads and saves the resources. To keep track of changes the server
* can be observed with a KoResourceServerObserver
*
* The \p Policy template parameter defines the way how the lifetime
* of a resource is handled. There are to predefined policies:
*
* o PointerStroragePolicy --- usual pointers with ownership over
* the resource.
* o SharedPointerStroragePolicy --- shared pointers. The server does no
* extra handling for the lifetime of
* the resource.
*
* Use the former for usual resources and the latter for shared pointer based
* ones.
*/
template <class T> class KoResourceServer : public KoResourceServerBase {
template <class T, class Policy = PointerStroragePolicy<T> >
class KoResourceServer : public KoResourceServerBase
{
public:
KoResourceServer(const QString& type, const QString& extensions, bool deleteResource = true)
typedef typename Policy::PointerType PointerType;
typedef KoResourceServerObserver<T, Policy> ObserverType;
public:
KoResourceServer(const QString& type, const QString& extensions)
: KoResourceServerBase(type, extensions)
, m_deleteResource(deleteResource)
{
m_blackListFile = KStandardDirs::locateLocal("data", "krita/" + type + ".blacklist");
m_blackListFileNames = readBlackListFile();
......@@ -129,16 +148,15 @@ public:
if (m_tagStore) {
delete m_tagStore;
}
if (m_deleteResource) {
foreach(KoResourceServerObserver<T>* observer, m_observers) {
observer->unsetResourceServer();
}
foreach(ObserverType* observer, m_observers) {
observer->unsetResourceServer();
}
foreach(T* res, m_resources) {
delete res;
}
foreach(PointerType res, m_resources) {
Policy::deleteResource(res);
}
m_resources.clear();
}
......@@ -169,8 +187,8 @@ public:
if (uniqueFiles.empty() || uniqueFiles.indexOf(fname) == -1) {
m_loadLock.lock();
uniqueFiles.append(fname);
QList<T*> resources = createResources(front);
foreach(T* resource, resources) {
QList<PointerType> resources = createResources(front);
foreach(PointerType resource, resources) {
Q_CHECK_PTR(resource);
if (resource->load() && resource->valid() && !resource->md5().isEmpty()) {
QByteArray md5 = resource->md5();
......@@ -189,7 +207,7 @@ public:
}
else {
kWarning() << "Loading resource " << front << "failed";
delete resource;
Policy::deleteResource(resource);
}
}
m_loadLock.unlock();
......@@ -204,7 +222,7 @@ public:
/// Adds an already loaded resource to the server
bool addResource(T* resource, bool save = true, bool infront = false) {
bool addResource(PointerType resource, bool save = true, bool infront = false) {
if (!resource->valid()) {
kWarning(30009) << "Tried to add an invalid resource!";
return false;
......@@ -252,7 +270,7 @@ public:
}
/// Remove a resource from Resource Server but not from a file
bool removeResourceFromServer(T* resource){
bool removeResourceFromServer(PointerType resource){
if ( !m_resourcesByFilename.contains( resource->shortFilename() ) ) {
return false;
}
......@@ -262,15 +280,12 @@ public:
m_resources.removeAt(m_resources.indexOf(resource));
notifyRemovingResource(resource);
if (m_deleteResource) {
delete resource;
}
Policy::deleteResource(resource);
return true;
}
/// Remove a resource from the resourceserver and blacklist it
bool removeResource(T* resource) {
bool removeResource(PointerType resource) {
if ( !m_resourcesByFilename.contains( resource->shortFilename() ) ) {
return false;
}
......@@ -282,16 +297,14 @@ public:
m_blackListFileNames.append(resource->filename());
writeBlackListFile();
if (m_deleteResource && resource) {
delete resource;
}
Policy::deleteResource(resource);
return true;
}
QList<T*> resources() {
QList<PointerType> resources() {
m_loadLock.lock();
QList<T*> resourceList = m_resources;
foreach(T* r, m_resourceBlackList) {
QList<PointerType> resourceList = m_resources;
foreach(PointerType r, m_resourceBlackList) {
resourceList.removeOne(r);
}
m_loadLock.unlock();
......@@ -316,13 +329,11 @@ public:
if ( fi.size() == 0)
return;
T* resource = createResource( filename );
PointerType resource = createResource( filename );
resource->load();
if(!resource->valid()){
kWarning(30009) << "Import failed! Resource is not valid";
if (m_deleteResource) {
delete resource;
}
Policy::deleteResource(resource);
return;
}
......@@ -342,9 +353,7 @@ public:
}
if(!addResource(resource)) {
if (m_deleteResource) {
delete resource;
}
Policy::deleteResource(resource);
}
}
......@@ -353,7 +362,7 @@ public:
{
QFileInfo fi(filename);
T* resource = resourceByFilename(fi.fileName());
PointerType resource = resourceByFilename(fi.fileName());
if (!resource) {
kWarning(30009) << "Resource file do not exist ";
return;
......@@ -369,14 +378,14 @@ public:
* @param observer the observer to be added
* @param notifyLoadedResources determines if the observer should be notified about the already loaded resources
*/
void addObserver(KoResourceServerObserver<T>* observer, bool notifyLoadedResources = true)
void addObserver(ObserverType* observer, bool notifyLoadedResources = true)
{
m_loadLock.lock();
if(observer && !m_observers.contains(observer)) {
m_observers.append(observer);
if(notifyLoadedResources) {
foreach(T* resource, m_resourcesByFilename) {
foreach(PointerType resource, m_resourcesByFilename) {
observer->resourceAdded(resource);
}
}
......@@ -388,7 +397,7 @@ public:
* Removes an observer from the server
* @param observer the observer to be removed
*/
void removeObserver(KoResourceServerObserver<T>* observer)
void removeObserver(ObserverType* observer)
{
int index = m_observers.indexOf( observer );
if( index < 0 )
......@@ -397,7 +406,7 @@ public:
m_observers.removeAt( index );
}
T* resourceByFilename(const QString& filename) const
PointerType resourceByFilename(const QString& filename) const
{
if (m_resourcesByFilename.contains(filename)) {
return m_resourcesByFilename[filename];
......@@ -406,7 +415,7 @@ public:
}
T* resourceByName( const QString& name ) const
PointerType resourceByName( const QString& name ) const
{
if (m_resourcesByName.contains(name)) {
return m_resourcesByName[name];
......@@ -414,7 +423,7 @@ public:
return 0;
}
T* resourceByMD5(const QByteArray& md5) const
PointerType resourceByMD5(const QByteArray& md5) const
{
return m_resourcesByMd5.value(md5);
}
......@@ -423,7 +432,7 @@ public:
* Call after changing the content of a resource;
* Notifies the connected views.
*/
void updateResource( T* resource )
void updateResource( PointerType resource )
{
notifyResourceChanged(resource);
}
......@@ -474,7 +483,7 @@ public:
void tagCategoryAdded(const QString& tag)
{
m_tagStore->serializeTags();
foreach(KoResourceServerObserver<T>* observer, m_observers) {
foreach(ObserverType* observer, m_observers) {
observer->syncTagAddition(tag);
}
}
......@@ -483,7 +492,7 @@ public:
{
m_tagStore->delTag(tag);
m_tagStore->serializeTags();
foreach(KoResourceServerObserver<T>* observer, m_observers) {
foreach(ObserverType* observer, m_observers) {
observer->syncTagRemoval(tag);
}
}
......@@ -491,7 +500,7 @@ public:
void tagCategoryMembersChanged()
{
m_tagStore->serializeTags();
foreach(KoResourceServerObserver<T>* observer, m_observers) {
foreach(ObserverType* observer, m_observers) {
observer->syncTaggedResourceView();
}
}
......@@ -508,44 +517,44 @@ public:
* Overide to create more resources from the file.
* @param filename the filename of the resource or resource collection
*/
virtual QList<T*> createResources( const QString & filename )
virtual QList<PointerType> createResources( const QString & filename )
{
QList<T*> createdResources;
QList<PointerType> createdResources;
createdResources.append(createResource(filename));
return createdResources;
}
virtual T* createResource( const QString & filename ) { return new T(filename); }
virtual PointerType createResource( const QString & filename ) { return new T(filename); }
protected:
/// Return the currently stored resources in alphabetical order, overwrite for customized sorting
virtual QList<T*> sortedResources()
virtual QList<PointerType> sortedResources()
{
QMap<QString, T*> sortedNames;
QMap<QString, PointerType> sortedNames;
foreach(const QString &name, m_resourcesByName.keys()) {
sortedNames.insert(name.toLower(), m_resourcesByName[name]);
}
return sortedNames.values();
}