65
class KIPIImageInfo : public KIPI::ImageInfoShared {
66
static const QRegExp sExtensionRE;
65
class KIPIImageInfo : public KIPI::ImageInfoShared
67
static const QRegExp sExtensionRE;
68
KIPIImageInfo(KIPI::Interface* interface, const KUrl& url) : KIPI::ImageInfoShared(interface, url) {}
71
QString txt=_url.fileName();
72
txt.replace('_', ' ');
73
txt.remove(sExtensionRE);
77
QString description() {
78
if (!_url.isLocalFile()) return QString();
81
bool ok=content.load(_url.toLocalFile());
82
if (!ok) return QString();
84
return content.comment();
87
void setDescription(const QString&) {}
92
if (!mMetaInfo.isValid()) {
96
const KFileMetaInfoItem& mii = mMetaInfo.item("http://freedesktop.org/standards/xesam/1.0/core#orientation");
98
const Orientation orientation = (Orientation)mii.value().toInt(&ok);
103
switch(orientation) {
121
kWarning() << "Can't represent an orientation value of" << orientation << "as an angle (" << _url << ')';
125
kWarning() << "Don't know how to handle an orientation value of" << orientation << '(' << _url << ')';
129
QMap<QString,QVariant> attributes() {
130
return QMap<QString,QVariant>();
133
void delAttributes( const QStringList& ) {}
135
void clearAttributes() {}
137
void addAttributes(const QMap<QString, QVariant>&) {}
69
KIPIImageInfo(KIPI::Interface* interface, const KUrl& url) : KIPI::ImageInfoShared(interface, url) {}
73
QString txt = _url.fileName();
74
txt.replace('_', ' ');
75
txt.remove(sExtensionRE);
81
if (!_url.isLocalFile()) return QString();
84
bool ok = content.load(_url.toLocalFile());
85
if (!ok) return QString();
87
return content.comment();
90
void setDescription(const QString&)
97
if (!mMetaInfo.isValid()) {
101
const KFileMetaInfoItem& mii = mMetaInfo.item("http://freedesktop.org/standards/xesam/1.0/core#orientation");
103
const Orientation orientation = (Orientation)mii.value().toInt(&ok);
108
switch (orientation) {
126
kWarning() << "Can't represent an orientation value of" << orientation << "as an angle (" << _url << ')';
130
kWarning() << "Don't know how to handle an orientation value of" << orientation << '(' << _url << ')';
134
QMap<QString, QVariant> attributes() {
135
return QMap<QString, QVariant>();
138
void delAttributes(const QStringList&)
141
void clearAttributes()
144
void addAttributes(const QMap<QString, QVariant>&)
140
KFileMetaInfo mMetaInfo;
148
KFileMetaInfo mMetaInfo;
142
void loadMetaInfo() {
143
if (!mMetaInfo.isValid()) {
144
mMetaInfo = KFileMetaInfo(_url);
152
if (!mMetaInfo.isValid()) {
153
mMetaInfo = KFileMetaInfo(_url);
149
const QRegExp KIPIImageInfo::sExtensionRE("\\.[a-z0-9]+$", Qt::CaseInsensitive );
158
const QRegExp KIPIImageInfo::sExtensionRE("\\.[a-z0-9]+$", Qt::CaseInsensitive);
152
160
struct MenuInfo {
154
QList<QAction*> mActions;
156
MenuInfo(const QString& name) : mName(name) {}
162
QList<QAction*> mActions;
164
MenuInfo(const QString& name) : mName(name) {}
158
166
typedef QMap<KIPI::Category, MenuInfo> MenuInfoMap;
161
168
struct KIPIInterfacePrivate {
163
MainWindow* mMainWindow;
165
KIPI::PluginLoader* mPluginLoader;
166
KIPI::PluginLoader::PluginList mPluginQueue;
167
MenuInfoMap mMenuInfoMap;
169
void setupPluginsMenu() {
170
mPluginMenu = static_cast<QMenu*>(
171
mMainWindow->factory()->container("plugins", mMainWindow));
172
QObject::connect(mPluginMenu, SIGNAL(aboutToShow()),
173
that, SLOT(loadPlugins()) );
176
void createDummyPluginAction(const QString& text) {
177
KAction* action = mMainWindow->actionCollection()->add<KAction>("dummy_plugin");
178
action->setText(text);
179
action->setShortcutConfigurable(false);
180
action->setEnabled(false);
181
mPluginMenu->addAction(action);
170
MainWindow* mMainWindow;
172
KIPI::PluginLoader* mPluginLoader;
173
KIPI::PluginLoader::PluginList mPluginQueue;
174
MenuInfoMap mMenuInfoMap;
176
void setupPluginsMenu()
178
mPluginMenu = static_cast<QMenu*>(
179
mMainWindow->factory()->container("plugins", mMainWindow));
180
QObject::connect(mPluginMenu, SIGNAL(aboutToShow()),
181
q, SLOT(loadPlugins()));
184
void createDummyPluginAction(const QString& text)
186
KAction* action = mMainWindow->actionCollection()->add<KAction>("dummy_plugin");
187
action->setText(text);
188
action->setShortcutConfigurable(false);
189
action->setEnabled(false);
190
mPluginMenu->addAction(action);
185
194
KIPIInterface::KIPIInterface(MainWindow* mainWindow)
186
:KIPI::Interface(mainWindow)
187
, d(new KIPIInterfacePrivate) {
189
d->mMainWindow = mainWindow;
190
d->mPluginLoader = 0;
195
: KIPI::Interface(mainWindow)
196
, d(new KIPIInterfacePrivate)
199
d->mMainWindow = mainWindow;
200
d->mPluginLoader = 0;
192
d->setupPluginsMenu();
193
QObject::connect(d->mMainWindow->contextManager(), SIGNAL(selectionChanged()),
194
this, SLOT(slotSelectionChanged()) );
195
QObject::connect(d->mMainWindow->contextManager(), SIGNAL(currentDirUrlChanged()),
196
this, SLOT(slotDirectoryChanged()) );
202
d->setupPluginsMenu();
203
QObject::connect(d->mMainWindow->contextManager(), SIGNAL(selectionChanged()),
204
this, SLOT(slotSelectionChanged()));
205
QObject::connect(d->mMainWindow->contextManager(), SIGNAL(currentDirUrlChanged()),
206
this, SLOT(slotDirectoryChanged()));
198
208
//TODO instead of delaying can we load them all at start-up to use actions somewhere else?
199
209
// delay a bit, so that it's called after loadPlugins()
200
QTimer::singleShot( 0, this, SLOT( init()));
210
QTimer::singleShot(0, this, SLOT(init()));
205
KIPIInterface::~KIPIInterface() {
210
static bool actionLessThan(QAction* a1, QAction* a2) {
211
QString a1Text = a1->text().replace("&", "");
212
QString a2Text = a2->text().replace("&", "");
213
return QString::compare(a1Text, a2Text, Qt::CaseInsensitive) < 0;
217
void KIPIInterface::loadPlugins() {
219
if (d->mPluginLoader) {
223
d->mMenuInfoMap[KIPI::ImagesPlugin] = MenuInfo(i18nc("@title:menu", "Images"));
224
d->mMenuInfoMap[KIPI::EffectsPlugin] = MenuInfo(i18nc("@title:menu", "Effects"));
225
d->mMenuInfoMap[KIPI::ToolsPlugin] = MenuInfo(i18nc("@title:menu", "Tools"));
226
d->mMenuInfoMap[KIPI::ImportPlugin] = MenuInfo(i18nc("@title:menu", "Import"));
227
d->mMenuInfoMap[KIPI::ExportPlugin] = MenuInfo(i18nc("@title:menu", "Export"));
228
d->mMenuInfoMap[KIPI::BatchPlugin] = MenuInfo(i18nc("@title:menu", "Batch Processing"));
229
d->mMenuInfoMap[KIPI::CollectionsPlugin] = MenuInfo(i18nc("@title:menu", "Collections"));
231
d->mPluginLoader = new KIPI::PluginLoader(QStringList(), this);
232
d->mPluginQueue = d->mPluginLoader->pluginList();
233
d->createDummyPluginAction(i18n("Loading..."));
237
void KIPIInterface::loadOnePlugin() {
238
while (!d->mPluginQueue.isEmpty()) {
239
KIPI::PluginLoader::Info* pluginInfo = d->mPluginQueue.takeFirst();
240
if (!pluginInfo->shouldLoad()) {
244
KIPI::Plugin* plugin = pluginInfo->plugin();
246
kWarning() << "Plugin from library" << pluginInfo->library() << "failed to load";
250
plugin->setup(d->mMainWindow);
251
QList<KAction*> actions = plugin->actions();
252
Q_FOREACH(KAction* action, actions) {
253
KIPI::Category category = plugin->category(action);
255
if (!d->mMenuInfoMap.contains(category)) {
256
kWarning() << "Unknown category '" << category;
260
d->mMenuInfoMap[category].mActions << action;
263
//plugin->actionCollection()->readShortcutSettings();
265
// If we reach this point, we just loaded one plugin. Go back to the
266
// event loop. We will come back to load the remaining plugins or create
268
QMetaObject::invokeMethod(this, "loadOnePlugin", Qt::QueuedConnection);
272
// If we reach this point, all plugins have been loaded. We can fill the
274
bool atLeastOnePluginLoaded = false;
275
MenuInfoMap::Iterator
276
it = d->mMenuInfoMap.begin(),
277
end = d->mMenuInfoMap.end();
278
for (; it != end; ++it) {
279
MenuInfo& info = it.value();
280
if (!info.mActions.isEmpty()) {
281
QMenu* menu = d->mPluginMenu->addMenu(info.mName);
282
qSort(info.mActions.begin(), info.mActions.end(), actionLessThan);
283
Q_FOREACH(QAction* action, info.mActions) {
284
atLeastOnePluginLoaded = true;
285
menu->addAction(action);
290
delete d->mMainWindow->actionCollection()->action("dummy_plugin");
291
if (!atLeastOnePluginLoaded) {
292
d->createDummyPluginAction(i18n("No Plugin Found"));
297
QList<QAction*> KIPIInterface::pluginActions(KIPI::Category category) const {
298
const_cast<KIPIInterface*>(this)->loadPlugins();
299
return d->mMenuInfoMap.value(category).mActions;
303
void KIPIInterface::init() {
304
slotDirectoryChanged();
305
slotSelectionChanged();
308
KIPI::ImageCollection KIPIInterface::currentAlbum() {
310
const ContextManager* contextManager = d->mMainWindow->contextManager();
311
const KUrl url = contextManager->currentDirUrl();
312
const SortedDirModel* model = contextManager->dirModel();
315
const int count = model->rowCount();
316
for (int row = 0; row < count; ++row) {
317
const QModelIndex& index = model->index(row, 0);
318
const KFileItem item = model->itemForIndex(index);
319
if (MimeTypeUtils::fileItemKind(item) == MimeTypeUtils::KIND_RASTER_IMAGE) {
320
list << item.targetUrl();
324
return KIPI::ImageCollection(new ImageCollection(url, url.fileName(), list));
328
KIPI::ImageCollection KIPIInterface::currentSelection() {
331
KFileItemList fileList = d->mMainWindow->contextManager()->selectedFileItemList();
332
KUrl::List list = fileList.urlList();
333
KUrl url = d->mMainWindow->contextManager()->currentUrl();
335
return KIPI::ImageCollection(new ImageCollection(url, url.fileName(), list));
339
QList<KIPI::ImageCollection> KIPIInterface::allAlbums() {
341
QList<KIPI::ImageCollection> list;
342
list << currentAlbum() << currentSelection();
347
KIPI::ImageInfo KIPIInterface::info(const KUrl& url) {
349
return KIPI::ImageInfo( new KIPIImageInfo(this, url) );
352
int KIPIInterface::features() const {
353
return KIPI::HostAcceptNewImages;
214
KIPIInterface::~KIPIInterface()
219
static bool actionLessThan(QAction* a1, QAction* a2)
221
QString a1Text = a1->text().replace("&", "");
222
QString a2Text = a2->text().replace("&", "");
223
return QString::compare(a1Text, a2Text, Qt::CaseInsensitive) < 0;
226
void KIPIInterface::loadPlugins()
229
if (d->mPluginLoader) {
233
d->mMenuInfoMap[KIPI::ImagesPlugin] = MenuInfo(i18nc("@title:menu", "Images"));
234
d->mMenuInfoMap[KIPI::EffectsPlugin] = MenuInfo(i18nc("@title:menu", "Effects"));
235
d->mMenuInfoMap[KIPI::ToolsPlugin] = MenuInfo(i18nc("@title:menu", "Tools"));
236
d->mMenuInfoMap[KIPI::ImportPlugin] = MenuInfo(i18nc("@title:menu", "Import"));
237
d->mMenuInfoMap[KIPI::ExportPlugin] = MenuInfo(i18nc("@title:menu", "Export"));
238
d->mMenuInfoMap[KIPI::BatchPlugin] = MenuInfo(i18nc("@title:menu", "Batch Processing"));
239
d->mMenuInfoMap[KIPI::CollectionsPlugin] = MenuInfo(i18nc("@title:menu", "Collections"));
241
d->mPluginLoader = new KIPI::PluginLoader(QStringList(), this);
242
d->mPluginQueue = d->mPluginLoader->pluginList();
243
d->createDummyPluginAction(i18n("Loading..."));
247
void KIPIInterface::loadOnePlugin()
249
while (!d->mPluginQueue.isEmpty()) {
250
KIPI::PluginLoader::Info* pluginInfo = d->mPluginQueue.takeFirst();
251
if (!pluginInfo->shouldLoad()) {
255
KIPI::Plugin* plugin = pluginInfo->plugin();
257
kWarning() << "Plugin from library" << pluginInfo->library() << "failed to load";
261
plugin->setup(d->mMainWindow);
262
QList<KAction*> actions = plugin->actions();
263
Q_FOREACH(KAction * action, actions) {
264
KIPI::Category category = plugin->category(action);
266
if (!d->mMenuInfoMap.contains(category)) {
267
kWarning() << "Unknown category '" << category;
271
d->mMenuInfoMap[category].mActions << action;
274
//plugin->actionCollection()->readShortcutSettings();
276
// If we reach this point, we just loaded one plugin. Go back to the
277
// event loop. We will come back to load the remaining plugins or create
279
QMetaObject::invokeMethod(this, "loadOnePlugin", Qt::QueuedConnection);
283
// If we reach this point, all plugins have been loaded. We can fill the
285
bool atLeastOnePluginLoaded = false;
286
MenuInfoMap::Iterator
287
it = d->mMenuInfoMap.begin(),
288
end = d->mMenuInfoMap.end();
289
for (; it != end; ++it) {
290
MenuInfo& info = it.value();
291
if (!info.mActions.isEmpty()) {
292
QMenu* menu = d->mPluginMenu->addMenu(info.mName);
293
qSort(info.mActions.begin(), info.mActions.end(), actionLessThan);
294
Q_FOREACH(QAction * action, info.mActions) {
295
atLeastOnePluginLoaded = true;
296
menu->addAction(action);
301
delete d->mMainWindow->actionCollection()->action("dummy_plugin");
302
if (!atLeastOnePluginLoaded) {
303
d->createDummyPluginAction(i18n("No Plugin Found"));
307
QList<QAction*> KIPIInterface::pluginActions(KIPI::Category category) const
309
const_cast<KIPIInterface*>(this)->loadPlugins();
310
return d->mMenuInfoMap.value(category).mActions;
313
void KIPIInterface::init()
315
slotDirectoryChanged();
316
slotSelectionChanged();
319
KIPI::ImageCollection KIPIInterface::currentAlbum()
322
const ContextManager* contextManager = d->mMainWindow->contextManager();
323
const KUrl url = contextManager->currentDirUrl();
324
const SortedDirModel* model = contextManager->dirModel();
327
const int count = model->rowCount();
328
for (int row = 0; row < count; ++row) {
329
const QModelIndex& index = model->index(row, 0);
330
const KFileItem item = model->itemForIndex(index);
331
if (MimeTypeUtils::fileItemKind(item) == MimeTypeUtils::KIND_RASTER_IMAGE) {
332
list << item.targetUrl();
336
return KIPI::ImageCollection(new ImageCollection(url, url.fileName(), list));
339
KIPI::ImageCollection KIPIInterface::currentSelection()
343
KFileItemList fileList = d->mMainWindow->contextManager()->selectedFileItemList();
344
KUrl::List list = fileList.urlList();
345
KUrl url = d->mMainWindow->contextManager()->currentUrl();
347
return KIPI::ImageCollection(new ImageCollection(url, url.fileName(), list));
350
QList<KIPI::ImageCollection> KIPIInterface::allAlbums()
353
QList<KIPI::ImageCollection> list;
354
list << currentAlbum() << currentSelection();
358
KIPI::ImageInfo KIPIInterface::info(const KUrl& url)
361
return KIPI::ImageInfo(new KIPIImageInfo(this, url));
364
int KIPIInterface::features() const
366
return KIPI::HostAcceptNewImages;
357
370
* KDirLister will pick up the image if necessary, so no updating is needed
358
371
* here, it is however necessary to discard caches if the plugin preserves timestamp
360
bool KIPIInterface::addImage(const KUrl&, QString&) {
361
//TODO setContext(const KUrl& currentUrl, const KFileItemList& selection)?
362
//Cache::instance()->invalidate( url );
373
bool KIPIInterface::addImage(const KUrl&, QString&)
375
//TODO setContext(const KUrl& currentUrl, const KFileItemList& selection)?
376
//Cache::instance()->invalidate( url );
366
void KIPIInterface::delImage(const KUrl&) {
380
void KIPIInterface::delImage(const KUrl&)
370
void KIPIInterface::refreshImages( const KUrl::List&) {
385
void KIPIInterface::refreshImages(const KUrl::List&)
374
KIPI::ImageCollectionSelector* KIPIInterface::imageCollectionSelector(QWidget *parent) {
375
return new KIPIImageCollectionSelector(this, parent);
378
KIPI::UploadWidget* KIPIInterface::uploadWidget(QWidget *parent) {
379
return (new KIPIUploadWidget(this, parent));
382
void KIPIInterface::slotSelectionChanged() {
383
emit selectionChanged(!d->mMainWindow->contextManager()->selectedFileItemList().isEmpty());
387
void KIPIInterface::slotDirectoryChanged() {
388
emit currentAlbumChanged(true);
390
KIPI::ImageCollectionSelector* KIPIInterface::imageCollectionSelector(QWidget *parent)
392
return new KIPIImageCollectionSelector(this, parent);
395
KIPI::UploadWidget* KIPIInterface::uploadWidget(QWidget *parent)
397
return (new KIPIUploadWidget(this, parent));
400
void KIPIInterface::slotSelectionChanged()
402
emit selectionChanged(!d->mMainWindow->contextManager()->selectedFileItemList().isEmpty());
405
void KIPIInterface::slotDirectoryChanged()
407
emit currentAlbumChanged(true);