1 /***************************************************************************
2 * file klflibbrowser.cpp
3 * This file is part of the KLatexFormula Project.
4 * Copyright (C) 2011 by Philippe Faist
5 * philippe.faist at bluewin.ch
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 /* $Id: klflibbrowser.cpp 1004 2017-02-02 20:07:10Z phfaist $ */
23
24 #include <QDebug>
25 #include <QUrl>
26 #include <QUrlQuery>
27 #include <QFile>
28 #include <QMenu>
29 #include <QAction>
30 #include <QEvent>
31 #include <QKeyEvent>
32 #include <QShortcut>
33 #include <QMessageBox>
34 #include <QSignalMapper>
35 #include <QLineEdit>
36 #include <QProgressDialog>
37 #include <QPushButton>
38 #include <QApplication>
39 #include <QClipboard>
40 #include <QDesktopServices>
41
42 #include "klfconfig.h"
43 #include <klfguiutil.h>
44 #include "klflibbrowser_p.h"
45 #include "klflibbrowser.h"
46 #include <ui_klflibbrowser.h>
47 #include "klfliblegacyengine.h"
48
49
KLFLibBrowser(QWidget * parent)50 KLFLibBrowser::KLFLibBrowser(QWidget *parent)
51 : QWidget(
52 #if defined(KLF_WS_WIN) || defined(KLF_WS_MAC)
53 0 /* parent */
54 #else
55 parent /* 0 */
56 #endif
57 , Qt::Window)
58 {
59 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
60 Q_UNUSED(parent) ;
61
62 u = new Ui::KLFLibBrowser;
63 u->setupUi(this);
64 u->tabResources->setContextMenuPolicy(Qt::CustomContextMenu);
65
66 KLF_DEBUG_ASSIGN_REF_INSTANCE(u->searchBar, "libbrowser-searchbar") ;
67 u->searchBar->registerShortcuts(this);
68 // set found/not-found colors
69 klfconfig.LibraryBrowser.colorFound.connectQObjectProperty(u->searchBar, "colorFound");
70 klfconfig.LibraryBrowser.colorNotFound.connectQObjectProperty(u->searchBar, "colorNotFound");
71
72 pResourceMenu = new QMenu(u->tabResources);
73 // connect actions
74 connect(u->aRename, SIGNAL(triggered()), this, SLOT(slotResourceRename()));
75 connect(u->aRenameSubRes, SIGNAL(triggered()), this, SLOT(slotResourceRenameSubResource()));
76 connect(u->aProperties, SIGNAL(triggered()), this, SLOT(slotResourceProperties()));
77 connect(u->aNewSubRes, SIGNAL(triggered()), this, SLOT(slotResourceNewSubRes()));
78 connect(u->aDelSubRes, SIGNAL(triggered()), this, SLOT(slotResourceDelSubRes()));
79 connect(u->aSaveTo, SIGNAL(triggered()), this, SLOT(slotResourceSaveTo()));
80 connect(u->aNew, SIGNAL(triggered()), this, SLOT(slotResourceNew()));
81 connect(u->aOpen, SIGNAL(triggered()), this, SLOT(slotResourceOpen()));
82 connect(u->aOpenExampleLibrary, SIGNAL(triggered()), this, SLOT(slotResourceOpenExampleLibrary()));
83 connect(u->aClose, SIGNAL(triggered()), this, SLOT(slotResourceClose()));
84 // and add them to menu
85 pResourceMenu->addAction((new KLFLibBrowserTabMenu(u->tabResources))->menuAction());
86 pResourceMenu->addSeparator();
87 pResourceMenu->addAction(u->aRename);
88 pResourceMenu->addAction(u->aRenameSubRes);
89 pResourceMenu->addAction(u->aProperties);
90 pResourceMenu->addSeparator();
91 pResourceMenu->addAction(u->aViewType);
92 pResourceMenu->addSeparator();
93 pResourceMenu->addAction(u->aNewSubRes);
94 pResourceMenu->addAction(u->aOpenSubRes);
95 pResourceMenu->addAction(u->aDelSubRes);
96 pResourceMenu->addSeparator();
97 pResourceMenu->addAction(u->aNew);
98 pResourceMenu->addAction(u->aOpen);
99 pResourceMenu->addAction(u->aOpenExampleLibrary);
100 /// \todo .......... save as copy action ............
101 // pResourceMenu->addAction(u->aSaveTo);
102 pResourceMenu->addAction(u->aClose);
103
104 slotRefreshResourceActionsEnabled();
105
106 pTabCornerButton = new QPushButton(u->tabResources);
107 pTabCornerButton->setMenu(pResourceMenu);
108 u->tabResources->setCornerWidget(pTabCornerButton);
109
110 connect(u->tabResources, SIGNAL(currentChanged(int)), this, SLOT(slotTabResourceShown(int)));
111 connect(u->tabResources, SIGNAL(customContextMenuRequested(const QPoint&)),
112 this, SLOT(slotShowTabContextMenu(const QPoint&)));
113
114 // RESTORE
115
116 QMenu * restoreMenu = new QMenu(this);
117 connect(u->aRestoreWithStyle, SIGNAL(triggered()), this, SLOT(slotRestoreWithStyle()));
118 connect(u->aRestoreLatexOnly, SIGNAL(triggered()), this, SLOT(slotRestoreLatexOnly()));
119 restoreMenu->addAction(u->aRestoreWithStyle);
120 restoreMenu->addAction(u->aRestoreLatexOnly);
121 u->btnRestore->setMenu(restoreMenu);
122
123 connect(u->btnRestore, SIGNAL(clicked()), this, SLOT(slotRestoreWithStyle()));
124 connect(u->btnDelete, SIGNAL(clicked()), this, SLOT(slotDeleteSelected()));
125 connect(u->aDelete, SIGNAL(triggered()), u->btnDelete, SLOT(animateClick()));
126
127 // IMPORT/EXPORT
128
129 pImportExportMenu = new QMenu(this);
130 pImportExportMenu->addAction(u->aOpenAll);
131 pImportExportMenu->addAction(u->aExport);
132 pImportExportMenu->addAction(u->aExportSelection);
133 u->btnImportExport->setMenu(pImportExportMenu);
134
135 connect(u->aOpenAll, SIGNAL(triggered()), this, SLOT(slotOpenAll()));
136 connect(u->aExport, SIGNAL(triggered()), this, SLOT(slotExport()));
137 connect(u->aExportSelection, SIGNAL(triggered()), this, SLOT(slotExportSelection()));
138
139
140 // CATEGORY/TAGS
141
142 connect(u->wEntryEditor, SIGNAL(metaInfoChanged(const QMap<int,QVariant>&)),
143 this, SLOT(slotMetaInfoChanged(const QMap<int,QVariant>&)));
144
145 connect(u->wEntryEditor, SIGNAL(restoreStyle(const KLFStyle&)),
146 this, SIGNAL(requestRestoreStyle(const KLFStyle&)));
147
148 // OPEN / NEW BUTTONS IN WELCOME TAB
149
150 connect(u->btnOpenRes, SIGNAL(clicked()), this, SLOT(slotResourceOpen()));
151 connect(u->btnCreateRes, SIGNAL(clicked()), this, SLOT(slotResourceNew()));
152
153 // SHORTCUTS
154
155 // cut/copy/paste
156 (void)new QShortcut(QKeySequence::Delete, this, SLOT(slotDeleteSelected()));
157 (void)new QShortcut(QKeySequence::Cut, this, SLOT(slotCut()));
158 (void)new QShortcut(QKeySequence::Copy, this, SLOT(slotCopy()));
159 (void)new QShortcut(QKeySequence::Paste, this, SLOT(slotPaste()));
160
161 retranslateUi(false);
162
163 // start with no entries selected
164 slotEntriesSelected(QList<KLFLibEntry>());
165 }
166
retranslateUi(bool alsoBaseUi)167 void KLFLibBrowser::retranslateUi(bool alsoBaseUi)
168 {
169 if (alsoBaseUi)
170 u->retranslateUi(this);
171
172 u->wEntryEditor->retranslateUi(alsoBaseUi);
173
174 pResourceMenu->setTitle(tr("Resource Actions", "[[menu title]]"));
175 u->searchBar->setFocusOutText(" "+tr("Hit Ctrl-F, Ctrl-S or / to search within the current resource"));
176 pTabCornerButton->setText(tr("Resource"));
177 }
178
179
~KLFLibBrowser()180 KLFLibBrowser::~KLFLibBrowser()
181 {
182 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
183
184 int k;
185 for (k = 0; k < pLibViews.size(); ++k) {
186 KLFLibResourceEngine * engine = pLibViews[k]->resourceEngine();
187 delete pLibViews[k];
188 delete engine;
189 }
190
191 delete u;
192 }
193
194
eventFilter(QObject * obj,QEvent * ev)195 bool KLFLibBrowser::eventFilter(QObject *obj, QEvent *ev)
196 {
197 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
198
199 if (obj->property("resourceTitleEditor").toBool() == true) {
200 if (ev->type() == QEvent::FocusOut) {
201 obj->deleteLater(); // if lost focus, cancel...
202 // don't eat event
203 }
204 if (ev->type() == QEvent::KeyPress) {
205 QKeyEvent *ke = (QKeyEvent*)ev;
206 if (ke->key() == Qt::Key_Escape) {
207 obj->deleteLater();
208 return true;
209 }
210 }
211 }
212
213 if (ev->type() == QEvent::Hide &&
214 obj->property("klf_libbrowser_pdlg_want_hideautodelete").toBool() == true) {
215 // this object is a resource-operation progress dialog that was just hidden
216 klfDbg( ": progress dialog was hidden, deleting." ) ;
217 obj->deleteLater();
218 return true;
219 // return false; // continue with event handling
220 }
221
222 return QWidget::eventFilter(obj, ev);
223 }
224
currentUrlIndex()225 int KLFLibBrowser::currentUrlIndex()
226 {
227 KLFLibBrowserViewContainer *viewc = curView();
228 if (viewc == NULL)
229 return -1;
230 return pLibViews.indexOf(viewc);
231 }
232
currentUrl()233 QUrl KLFLibBrowser::currentUrl()
234 {
235 int i = currentUrlIndex();
236 if (i < 0 || i >= pLibViews.size())
237 return QUrl();
238 return pLibViews[i]->url();
239 }
240
241
openUrls() const242 QList<QUrl> KLFLibBrowser::openUrls() const
243 {
244 QList<QUrl> urls;
245 int k;
246 for (k = 0; k < pLibViews.size(); ++k) {
247 urls << pLibViews[k]->url();
248 }
249 return urls;
250 }
251
getOpenResource(const QUrl & url)252 KLFLibResourceEngine * KLFLibBrowser::getOpenResource(const QUrl& url)
253 {
254 KLFLibBrowserViewContainer * viewc = findOpenUrl(url);
255 if (viewc == NULL)
256 return NULL;
257 return viewc->resourceEngine();
258 }
259
getView(const QUrl & url)260 KLFAbstractLibView * KLFLibBrowser::getView(const QUrl& url)
261 {
262 KLFLibBrowserViewContainer * viewc = findOpenUrl(url);
263 if (viewc == NULL)
264 return NULL;
265 return viewc->view();
266 }
267
getView(KLFLibResourceEngine * resource)268 KLFAbstractLibView * KLFLibBrowser::getView(KLFLibResourceEngine *resource)
269 {
270 KLFLibBrowserViewContainer * viewc = findOpenResource(resource);
271 if (viewc == NULL)
272 return NULL;
273 return viewc->view();
274 }
275
276
277
saveGuiState()278 QVariantMap KLFLibBrowser::saveGuiState()
279 {
280 QVariantMap v;
281 // first save the list of open URLs
282 QList<QUrl> myurllist = openUrls();
283 QUrl currenturl = currentUrl();
284 QList<QVariant> urllist; // will hold URL's as QUrl's
285 QList<QVariant> viewstatelist; // will hold variantMap's
286 QList<QVariant> resroleflagslist; // will hold quint32's
287
288 int k;
289 for (k = 0; k < myurllist.size(); ++k) {
290 KLFLibBrowserViewContainer *viewc = findOpenUrl(myurllist[k]);
291 if (viewc == NULL) {
292 qWarning()<<"Should NOT HAPPEN! viewc is NULL in KLFLibBrowser::saveGuiState()! URL-List=\n"
293 <<myurllist;
294 continue;
295 }
296 QVariantMap viewState = viewc->saveGuiState();
297 urllist << QVariant::fromValue<QUrl>(myurllist[k]);
298 viewstatelist << QVariant::fromValue<QVariantMap>(viewState);
299 resroleflagslist << QVariant::fromValue<quint32>(viewc->resourceRoleFlags());
300 }
301 v["UrlList"] = QVariant::fromValue<QVariantList>(urllist);
302 v["ViewStateList"] = QVariant::fromValue<QVariantList>(viewstatelist);
303 v["ResourceRoleFlagsList"] = QVariant::fromValue<QVariantList>(resroleflagslist);
304 v["CurrentUrl"] = QVariant::fromValue<QUrl>(currenturl);
305 v["WidgetSize"] = QVariant::fromValue<QSize>(size());
306 return v;
307 }
loadGuiState(const QVariantMap & v,bool openURLs)308 void KLFLibBrowser::loadGuiState(const QVariantMap& v, bool openURLs)
309 {
310 QUrl currenturl = v["CurrentUrl"].toUrl();
311 QList<QVariant> urllist = v["UrlList"].toList();
312 QList<QVariant> viewstatelist = v["ViewStateList"].toList();
313 QList<QVariant> resroleflagslist = v["ResourceRoleFlagsList"].toList();
314 QSize widgetsize = v["WidgetSize"].value<QSize>();
315 int k;
316 for (k = 0; k < urllist.size(); ++k) {
317 QUrl url = urllist[k].toUrl();
318 quint32 flags = resroleflagslist[k].value<quint32>();
319 klfDbg( "LibBrowser::loadGuiState: Opening url "<<url<<" with flags="<<flags ) ;
320 QVariantMap viewState = viewstatelist[k].toMap();
321 // don't open new URLs if openURLs is false
322 if ( !openURLs && findOpenUrl(url) == NULL )
323 continue;
324 // open this URL
325 bool res = openResourceFromGuiState(url, viewState);
326 // ignore flags, in case we eg. change library file, don't keep the old ones uncloseable
327 // updateResourceRoleFlags(..., flags);
328 if ( ! res ) {
329 qWarning()<<"KLFLibBrowser::loadGuiState: Can't open resource "<<url<<"! (flags="
330 <<flags<<")";
331 continue;
332 }
333 }
334 klfDbg( "Almost finished loading gui state." ) ;
335 KLFLibBrowserViewContainer *curviewc = findOpenUrl(currenturl);
336 if (curviewc != NULL)
337 u->tabResources->setCurrentWidget(curviewc);
338 klfDbg( "Loaded GUI state." ) ;
339
340 if (widgetsize.width() > 0 && widgetsize.height() > 0)
341 resize(widgetsize);
342 }
343
344
345
346 // static
displayTitle(KLFLibResourceEngine * resource)347 QString KLFLibBrowser::displayTitle(KLFLibResourceEngine *resource)
348 {
349 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
350
351 KLF_ASSERT_NOT_NULL( resource, "Resource is NULL!", return QString() ) ;
352
353 QString basestr;
354 if (resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) {
355 QString subresourcetitle = resource->defaultSubResource();
356 if (resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps)
357 subresourcetitle
358 = resource->subResourceProperty(resource->defaultSubResource(),
359 KLFLibResourceEngine::SubResPropTitle).toString();
360 basestr = QString("%1 - %2").arg(resource->title(), subresourcetitle);
361 } else {
362 basestr = resource->title();
363 }
364 if (!resource->canModifyData(KLFLibResourceEngine::AllActionsData)) {
365 // basestr = "# "+basestr; // this is confusing
366 }
367 return basestr;
368 }
369
370
findOpenUrl(const QUrl & url)371 KLFLibBrowserViewContainer * KLFLibBrowser::findOpenUrl(const QUrl& url)
372 {
373 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
374
375 klfDbg( "\turl is "<<url ) ;
376 int k;
377 for (k = 0; k < pLibViews.size(); ++k) {
378 klfDbg("\t\ttest lib view #"<<k) ;
379 klfDbg("\t\turl="<<pLibViews[k]->url() ) ;
380 // allow: * urls to be equal
381 // * this resource's URL to be less specific (shows more) than what we're searching for
382 uint fl = pLibViews[k]->view()->compareUrlTo(url, KlfUrlCompareEqual|KlfUrlCompareLessSpecific);
383 if (fl & KlfUrlCompareEqual ||
384 fl & KlfUrlCompareLessSpecific) {
385 klfDbg( ": Found!" ) ;
386 return pLibViews[k];
387 }
388 }
389 return NULL;
390 }
391
findOpenResource(KLFLibResourceEngine * resource)392 KLFLibBrowserViewContainer * KLFLibBrowser::findOpenResource(KLFLibResourceEngine *resource)
393 {
394 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
395
396 int k;
397 for (k = 0; k < pLibViews.size(); ++k)
398 if (pLibViews[k]->resourceEngine() == resource)
399 return pLibViews[k];
400 return NULL;
401 }
402
curView()403 KLFLibBrowserViewContainer * KLFLibBrowser::curView()
404 {
405 return qobject_cast<KLFLibBrowserViewContainer*>(u->tabResources->currentWidget());
406 }
curLibView()407 KLFAbstractLibView * KLFLibBrowser::curLibView()
408 {
409 KLFLibBrowserViewContainer *v = curView();
410 if (v == NULL)
411 return NULL;
412 return v->view();
413 }
viewForTabIndex(int tab)414 KLFLibBrowserViewContainer * KLFLibBrowser::viewForTabIndex(int tab)
415 {
416 return qobject_cast<KLFLibBrowserViewContainer*>(u->tabResources->widget(tab));
417 }
findByRoleFlags(uint testflags,uint mask)418 QList<KLFLibBrowserViewContainer*> KLFLibBrowser::findByRoleFlags(uint testflags, uint mask)
419 {
420 klfDbg("Looking for flags "<<klfFmtCC("%#010x", testflags)<<" with mask "<<klfFmtCC("%#010x", mask)) ;
421 QList<KLFLibBrowserViewContainer *> list;
422 int k;
423 for (k = 0; k < pLibViews.size(); ++k) {
424 if ((pLibViews[k]->resourceRoleFlags() & mask) == testflags) {
425 klfDbg("Adding #"<<k<<": "<<pLibViews[k]<<", url="<<pLibViews[k]->url()) ;
426 list << pLibViews[k];
427 }
428 }
429 return list;
430 }
431
432
433
openResource(const QString & url,uint resourceRoleFlags,const QString & viewTypeIdentifier)434 bool KLFLibBrowser::openResource(const QString& url, uint resourceRoleFlags,
435 const QString& viewTypeIdentifier)
436 {
437 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME+QString("(QString,uint,QString)")) ;
438 return openResource(QUrl(url), resourceRoleFlags, viewTypeIdentifier);
439 }
440
openResource(const QUrl & url,uint resourceRoleFlags,const QString & viewTypeIdentifier)441 bool KLFLibBrowser::openResource(const QUrl& url, uint resourceRoleFlags,
442 const QString& viewTypeIdentifier)
443 {
444 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME+"(QUrl,uint,QString)") ;
445 klfDbg( " url="<<url.toString()<<"; resroleflags="<<resourceRoleFlags
446 <<"; vtypeidentifier="<<viewTypeIdentifier ) ;
447
448 KLFLibBrowserViewContainer * openview = findOpenUrl(url);
449 if (openview != NULL) {
450 qDebug("KLFLibBrowser::openResource(%s,%u): This resource is already open.",
451 qPrintable(url.toString()), resourceRoleFlags);
452 if ((resourceRoleFlags & OpenNoRaise) == 0)
453 u->tabResources->setCurrentWidget(openview);
454 updateResourceRoleFlags(openview, resourceRoleFlags);
455 return true;
456 }
457
458 KLFLibEngineFactory * factory = KLFLibEngineFactory::findFactoryFor(url.scheme());
459 if ( factory == NULL ) {
460 qWarning()<<KLF_FUNC_NAME<<": failed to find appropriate factory for url="<<url.toString()<<"!";
461 return false;
462 }
463 KLFLibResourceEngine * resource = factory->openResource(url, this);
464 if ( resource == NULL ) {
465 qWarning()<<KLF_FUNC_NAME<<": factory failed to open resource "<<url.toString()<<"!";
466 return false;
467 }
468
469 // go on opening resource with our sister function
470 return openResource(resource, resourceRoleFlags, viewTypeIdentifier);
471 }
openResource(KLFLibResourceEngine * resource,uint resourceRoleFlags,const QString & viewTypeIdentifier)472 bool KLFLibBrowser::openResource(KLFLibResourceEngine *resource, uint resourceRoleFlags,
473 const QString& viewTypeIdentifier)
474 {
475 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME+"(KLFLibResourceEngine*,uint,QString)") ;
476 klfDbg( "\topening resource url="
477 <<resource->url(KLFLibResourceEngine::WantUrlDefaultSubResource).toString() ) ;
478
479 // KLFPleaseWaitPopup label(tr("Loading resource, please wait..."), this);
480
481 KLF_ASSERT_NOT_NULL(resource,
482 "resource pointer is NULL! (flags="<<resourceRoleFlags<<",vti="<<viewTypeIdentifier<<")",
483 return false );
484
485 KLFLibBrowserViewContainer * openview = findOpenResource(resource);
486 if (openview != NULL) {
487 qDebug("KLFLibBrowser::openResource(%p,%u): This resource is already open.",
488 (void*)resource, resourceRoleFlags);
489 if ((resourceRoleFlags & OpenNoRaise) == 0)
490 u->tabResources->setCurrentWidget(openview);
491 updateResourceRoleFlags(openview, resourceRoleFlags);
492 return true;
493 }
494
495 resource->setParent(this);
496
497 klfDbgT(": created resource. about to create view container.") ;
498
499 // now create appropriate view for this resource
500 KLFLibBrowserViewContainer *viewc = new KLFLibBrowserViewContainer(resource, u->tabResources);
501
502 klfDbgT(": adding tab page....") ;
503
504 int i = u->tabResources->addTab(viewc, displayTitle(resource));
505 if ((resourceRoleFlags & OpenNoRaise) == 0)
506 u->tabResources->setCurrentWidget(viewc);
507 u->tabResources
508 ->refreshTabReadOnly(i, !resource->canModifyData(KLFLibResourceEngine::AllActionsData));
509 pLibViews.append(viewc);
510 setStyleSheet(styleSheet());
511 updateResourceRoleFlags(viewc, resourceRoleFlags);
512
513
514 // get informed about selection changes
515 connect(viewc, SIGNAL(entriesSelected(const KLFLibEntryList& )),
516 this, SLOT(slotEntriesSelected(const KLFLibEntryList& )));
517 // and of new category suggestions
518 connect(viewc, SIGNAL(moreCategorySuggestions(const QStringList&)),
519 this, SLOT(slotAddCategorySuggestions(const QStringList&)));
520
521 connect(viewc, SIGNAL(requestRestore(const KLFLibEntry&, uint)),
522 this, SIGNAL(requestRestore(const KLFLibEntry&, uint)));
523 connect(viewc, SIGNAL(requestRestoreStyle(const KLFStyle&)),
524 this, SIGNAL(requestRestoreStyle(const KLFStyle&)));
525
526 connect(viewc, SIGNAL(requestOpenUrl(const QString&)),
527 this, SLOT(openResource(const QString&)));
528
529 connect(viewc, SIGNAL(resourceDataChanged(const QList<KLFLib::entryId>&)),
530 this, SLOT(slotResourceDataChanged(const QList<KLFLib::entryId>&)));
531 connect(resource, SIGNAL(resourcePropertyChanged(int)),
532 this, SLOT(slotResourcePropertyChanged(int)));
533 connect(resource, SIGNAL(subResourcePropertyChanged(const QString&, int)),
534 this, SLOT(slotSubResourcePropertyChanged(const QString&, int)));
535 connect(resource, SIGNAL(defaultSubResourceChanged(const QString&)),
536 this, SLOT(slotDefaultSubResourceChanged(const QString&)));
537
538 // progress reporting originating from resource (eg. database operations)
539 connect(resource, SIGNAL(operationStartReportingProgress(KLFProgressReporter *, const QString&)),
540 this, SLOT(slotStartProgress(KLFProgressReporter *, const QString&)));
541 // progress reporting originating from view (eg. model updates)
542 connect(viewc, SIGNAL(viewOperationStartReportingProgress(KLFProgressReporter *, const QString&)),
543 this, SLOT(slotStartProgress(KLFProgressReporter *, const QString&)));
544
545 // supply a context menu to view
546 connect(viewc, SIGNAL(viewContextMenuRequested(const QPoint&)),
547 this, SLOT(slotShowContextMenu(const QPoint&)));
548
549
550 // create a list of view types to attempt to open, in a given priority order
551 QStringList viewtypeident_try;
552 // * the argument to this function
553 viewtypeident_try << viewTypeIdentifier;
554 if ((resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) &&
555 (resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps)) {
556 // * the sub-resource view type property (if applicable)
557 viewtypeident_try
558 << resource->subResourceProperty(resource->defaultSubResource(),
559 KLFLibResourceEngine::SubResPropViewType).toString();
560 }
561 // * the resource view type property
562 viewtypeident_try << resource->viewType();
563 // * the suggested view type for this resource (as given by engine itself)
564 viewtypeident_try << resource->suggestedViewTypeIdentifier();
565 // * the default view type suggested by the factory
566 viewtypeident_try << KLFLibViewFactory::defaultViewTypeIdentifier();
567 // * a "default" view type (last resort, hoping it exists!)
568 viewtypeident_try << QLatin1String("default");
569
570 klfDbgT(": created resource. about to test view types.") ;
571 klfDbg( "\tView types: "<<viewtypeident_try ) ;
572
573 int k;
574 // try each view type, first success is kept.
575 for (k = 0; k < viewtypeident_try.size(); ++k) {
576 if (viewtypeident_try[k].isEmpty())
577 continue;
578
579 KLFLibViewFactory *viewfactory =
580 KLFLibViewFactory::findFactoryFor(viewtypeident_try[k]);
581 if (viewfactory == NULL) {
582 klfDbg( "can't find view factory for view type identifier "
583 <<viewtypeident_try[k]<<"!" ) ;
584 continue;
585 }
586 if ( ! viewfactory->canCreateLibView(viewtypeident_try[k], resource) ) {
587 klfDbg( "incompatible view type identifier "<<viewtypeident_try[k]
588 <<"for resource "<<resource->url()<<"." ) ;
589 continue;
590 }
591 bool r = viewc->openView(viewtypeident_try[k]);
592 if (!r) {
593 klfDbg( "can't create view! viewtypeident="<<viewtypeident_try[k]<<"." ) ;
594 continue;
595 }
596
597 klfDbgT(": found and instantiated good view type="<<viewtypeident_try[k]) ;
598
599 // found good view type !
600 resource->setViewType(viewtypeident_try[k]);
601 // quit for() on first success.
602 break;
603 }
604
605 klfDbgT(": requiring cat suggestions.") ;
606
607 // get more category completions
608 viewc->view()->wantMoreCategorySuggestions();
609
610 // hide welcome page if it's shown
611 if ((i = u->tabResources->indexOf(u->tabWelcome)) != -1)
612 u->tabResources->removeTab(i);
613
614 klfDbgT(": end of function") ;
615
616 return true;
617 }
618
openResourceFromGuiState(const QUrl & url,const QVariantMap & guiState)619 bool KLFLibBrowser::openResourceFromGuiState(const QUrl& url, const QVariantMap& guiState)
620 {
621 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
622 // peek into GUI state to open the correct view
623 QString vti = guiState.value(QLatin1String("CurrentViewTypeIdentifier")).toString();
624 klfDbg("view-type-identifier is "<<vti<<"; guiState is "<<guiState) ;
625 bool result = openResource(url, NoChangeFlag, vti);
626 if (!result)
627 return false;
628 klfDbg("restoring gui state..") ;
629 KLFLibBrowserViewContainer *viewc = findOpenUrl(url);
630 KLF_ASSERT_NOT_NULL( viewc, "can't find the view container we just opened!", return false ) ;
631 viewc->loadGuiState(guiState);
632 return true;
633 }
634
635
closeResource(const QUrl & url)636 bool KLFLibBrowser::closeResource(const QUrl& url)
637 {
638 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
639
640 KLFLibBrowserViewContainer * w = findOpenUrl(url);
641 if (w == NULL)
642 return false;
643
644 return slotResourceClose(w);
645 }
646
647
updateResourceRoleFlags(KLFLibBrowserViewContainer * viewc,uint resroleflags)648 void KLFLibBrowser::updateResourceRoleFlags(KLFLibBrowserViewContainer *viewc, uint resroleflags)
649 {
650 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
651
652 KLF_ASSERT_NOT_NULL(viewc, "the viewc parameter is null!", return; ) ;
653
654 if (resroleflags & NoChangeFlag)
655 return;
656
657 // only store flags that don't act 'now'
658 resroleflags = resroleflags & ~NowMask;
659
660 klfDbg("updating flags for resource="<<viewc->url()<<"; flags after mask="
661 <<klfFmtCC("%#010x", resroleflags)) ;
662
663 // If history resroleflags is set, then unset that flag to its previous owner (history role flag
664 // is exclusive).
665 // Same respectively for archive flag.
666 uint exclusive_flag_list[] = { HistoryRoleFlag, ArchiveRoleFlag, 0 } ;
667 int j;
668 for (j = 0; exclusive_flag_list[j] != 0; ++j) {
669 uint xflag = exclusive_flag_list[j];
670 if (resroleflags & xflag) {
671 // If we are about to set this flag to resource 'viewc', then make sure no one (else) has it
672 int k;
673 for (k = 0; k < pLibViews.size(); ++k) {
674 if (pLibViews[k] == viewc)
675 continue; // skip our targeted view
676 uint fl = pLibViews[k]->resourceRoleFlags();
677 if (fl & xflag) {
678 // unset it
679 pLibViews[k]->setResourceRoleFlags(fl & ~xflag);
680 }
681 }
682 }
683 }
684
685 // now we can set the appropriate flags on the requested resource view
686 viewc->setResourceRoleFlags(resroleflags);
687 }
688
689
slotTabResourceShown(int tabIndex)690 void KLFLibBrowser::slotTabResourceShown(int tabIndex)
691 {
692 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
693 klfDbg( "\t tabIndex="<<tabIndex ) ;
694
695 KLFLibBrowserViewContainer * viewc =
696 qobject_cast<KLFLibBrowserViewContainer*>(u->tabResources->widget(tabIndex));
697 if (viewc == NULL || tabIndex < 0) {
698 emit resourceTabChanged(QUrl());
699 return;
700 }
701
702 // redirect searches to the correct view
703 u->searchBar->setSearchTarget(viewc);
704
705 klfDbg("setting up view type menu...") ;
706
707 // set up view type menu appropriately
708 QList<QAction*> actions = viewc->viewTypeActions();
709 QMenu *viewTypeMenu = u->aViewType->menu();
710 if (viewTypeMenu == NULL) {
711 viewTypeMenu = new QMenu(this);
712 u->aViewType->setMenu(viewTypeMenu);
713 KLF_DEBUG_WATCH_OBJECT(viewTypeMenu) ;
714 }
715 viewTypeMenu->clear();
716 int k;
717 for (k = 0; k < actions.size(); ++k) {
718 viewTypeMenu->addAction(actions[k]);
719 }
720
721 QMenu * openSubResMenu = u->aOpenSubRes->menu();
722 if (openSubResMenu == NULL) {
723 openSubResMenu = new QMenu(this);
724 u->aOpenSubRes->setMenu(openSubResMenu);
725 KLF_DEBUG_WATCH_OBJECT(openSubResMenu) ;
726 }
727 openSubResMenu->clear();
728 QList<QAction*> openSubResActions = viewc->openSubResourceActions();
729 for (k = 0; k < openSubResActions.size(); ++k) {
730 openSubResMenu->addAction(openSubResActions[k]);
731 }
732 if (openSubResActions.size() > 0)
733 u->aOpenSubRes->setEnabled(true);
734 else
735 u->aOpenSubRes->setEnabled(false);
736
737 // refresh selection-related displays
738 KLFAbstractLibView *view = viewc->view();
739 if (view != NULL)
740 slotEntriesSelected(view->selectedEntries());
741 slotRefreshResourceActionsEnabled();
742
743 emit resourceTabChanged(viewc->url());
744 }
745
slotShowTabContextMenu(const QPoint & pos)746 void KLFLibBrowser::slotShowTabContextMenu(const QPoint& pos)
747 {
748 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
749
750 int tab = u->tabResources->getTabAtPoint(pos);
751 if (tab != -1) {
752 u->tabResources->setCurrentIndex(tab);
753 }
754 pResourceMenu->popup(u->tabResources->mapToGlobal(pos));
755 }
756
slotResourceRename()757 void KLFLibBrowser::slotResourceRename()
758 {
759 slotResourceRename(false);
760 }
slotResourceRenameSubResource()761 void KLFLibBrowser::slotResourceRenameSubResource()
762 {
763 slotResourceRename(true);
764 }
slotResourceRename(bool renamingSubResource)765 void KLFLibBrowser::slotResourceRename(bool renamingSubResource)
766 {
767 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
768 klfDbg("renamingSubResource="<<renamingSubResource) ;
769
770 int tab = u->tabResources->currentIndex();
771 KLFLibBrowserViewContainer * viewc = curView();
772 if (tab < 0 || viewc == NULL)
773 return;
774
775 klfDbg( ": Rename! renamingSubResource="<<renamingSubResource ) ;
776
777 KLFLibResourceEngine *res = viewc->resourceEngine();
778
779 if ( ! renamingSubResource && ! res->canModifyProp(KLFLibResourceEngine::PropTitle) )
780 return;
781
782 if ( renamingSubResource &&
783 ( !(res->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) ||
784 !(res->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps) ||
785 !(res->canModifySubResourceProperty(res->defaultSubResource(),
786 KLFLibResourceEngine::SubResPropTitle))
787 ) )
788 return;
789
790 QLineEdit * editor = new QLineEdit(u->tabResources);
791 editor->setGeometry(u->tabResources->getTabRect(tab));
792 editor->show();
793 if (!renamingSubResource)
794 editor->setText(res->title());
795 else
796 editor->setText(res->subResourceProperty(res->defaultSubResource(),
797 KLFLibResourceEngine::SubResPropTitle).toString());
798 editor->setFocus();
799 editor->setProperty("tabURL", viewc->url());
800 editor->setProperty("resourceTitleEditor", true);
801 editor->setProperty("needsBackground", true);
802 editor->setProperty("renamingSubResource", renamingSubResource);
803 editor->setStyleSheet("");
804 editor->installEventFilter(this);
805
806 // kill editor if tab changes
807 connect(u->tabResources, SIGNAL(currentChanged(int)), editor, SLOT(deleteLater()));
808 connect(editor, SIGNAL(returnPressed()), this, SLOT(slotResourceRenameFinished()));
809 }
810
slotResourceRenameFinished()811 void KLFLibBrowser::slotResourceRenameFinished()
812 {
813 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
814
815 QObject * editor = sender();
816 if (editor == NULL) {
817 qWarning("KLFLibBrowser::slotResourceRenameFinished: no sender!");
818 return;
819 }
820 bool isRenamingSubResource = editor->property("renamingSubResource").toBool();
821 QUrl url = editor->property("tabURL").toUrl();
822 KLFLibBrowserViewContainer * viewc = findOpenUrl(url);
823 if (viewc == NULL) {
824 qWarning()<<KLF_FUNC_NAME<<": can't find the resource with URL "<<url;
825 return;
826 }
827 KLFLibResourceEngine *res = viewc->resourceEngine();
828 QString text = editor->property("text").toString();
829 if (!isRenamingSubResource)
830 res->setTitle(text);
831 else
832 res->setSubResourceProperty(res->defaultSubResource(), KLFLibResourceEngine::SubResPropTitle,
833 QVariant::fromValue<QString>(text));
834
835 editor->deleteLater();
836 }
837
slotResourceClose(KLFLibBrowserViewContainer * view,bool force)838 bool KLFLibBrowser::slotResourceClose(KLFLibBrowserViewContainer *view, bool force)
839 {
840 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
841
842 if (view == NULL)
843 view = curView();
844 if (view == NULL)
845 return false;
846
847 if (!force && view->resourceRoleFlags() & NoCloseRoleFlag) // sorry, can't close.
848 return false;
849
850 klfDbg( "Close! resflags="<<view->resourceRoleFlags() ) ;
851
852 int tabindex = u->tabResources->indexOf(view);
853 if (tabindex < 0) {
854 qWarning("KLFLibBrowser::closeResource(url): can't find view in tab widget?!?\n"
855 "\turl=%s, viewwidget=%p", qPrintable(view->url().toString()), (void*)view);
856 return false;
857 }
858
859 if (!force && klfconfig.LibraryBrowser.confirmClose) {
860 // ask user for confirmation
861 QMessageBox::StandardButton btn =
862 QMessageBox::question(this, tr("Close Resource"), tr("Do you want to close this resource?"),
863 QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes);
864 if (btn != QMessageBox::Yes)
865 return false;
866 }
867
868 u->tabResources->removeTab(tabindex);
869 int index = pLibViews.indexOf(view);
870 pLibViews.removeAt(index);
871 // delete view and engine
872 KLFLibResourceEngine *resource = view->resourceEngine();
873 delete view;
874 delete resource;
875
876 if (u->tabResources->count() == 0)
877 u->tabResources->addTab(u->tabWelcome, QIcon(":/pics/library.png"), tr("Library Browser"));
878
879 return true;
880 }
881
slotResourceProperties()882 void KLFLibBrowser::slotResourceProperties()
883 {
884 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
885
886 KLFLibBrowserViewContainer *view = curView();
887 if (view == NULL) {
888 qWarning("KLFLibBrowser::slotResourceProperties: NULL View!");
889 return;
890 }
891 KLFLibResPropEditorDlg * dialog = new KLFLibResPropEditorDlg(view->resourceEngine(), this);
892 dialog->show();
893 }
894
slotResourceNewSubRes()895 bool KLFLibBrowser::slotResourceNewSubRes()
896 {
897 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
898
899 KLFLibBrowserViewContainer *view = curView();
900 if (view == NULL) {
901 qWarning("KLFLibBrowser::slotResourceProperties: NULL View!");
902 return false;
903 }
904 KLFLibResourceEngine *res = view->view()->resourceEngine();
905 QString name = KLFLibNewSubResDlg::createSubResourceIn(res, this);
906 if (name.isEmpty())
907 return false;
908
909 // see remark in comment below
910 QUrl url = res->url();
911 QUrlQuery urlq(url);
912 urlq.removeAllQueryItems("klfDefaultSubResource");
913 urlq.addQueryItem("klfDefaultSubResource", name);
914 url.setQuery(urlq);
915
916 klfDbg( "KLFLibBrowser::slotRes.New.S.Res(): Create sub-resource named "<<name<<", opening "<<url ) ;
917
918 // in case of a view displaying all sub-resources, this also works because findOpenUrl() will find
919 // that view and raise it.
920 return openResource(url);
921 }
922
slotResourceDelSubRes()923 bool KLFLibBrowser::slotResourceDelSubRes()
924 {
925 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
926
927 KLFLibBrowserViewContainer *viewc = curView();
928 KLF_ASSERT_NOT_NULL(viewc , "NULL View Container!" , return false; ) ;
929 KLFAbstractLibView *view = viewc->view();
930 KLF_ASSERT_NOT_NULL(view , "NULL View in container "<<viewc<<" !" , return false; ) ;
931 KLFLibResourceEngine *res = view->resourceEngine();
932 KLF_ASSERT_NOT_NULL(res , "NULL resource for view="<<view<<" !" , return false; ) ;
933
934 KLF_ASSERT_CONDITION( res->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources ,
935 "Sub-resources are not supported in resource "<<res->url()<<"!"
936 " Cannot delete sub-resource!",
937 return false; ) ;
938
939 if (res->subResourceList().size() <= 1) {
940 QMessageBox::warning(this, tr("Error"),
941 tr("You may not delete the last remaining sub-resource of this resource."));
942 klfDbg("Attempted to delete last remaining sub-resource"<<res->defaultSubResource()<<" of resource "
943 <<res->url()<<". Not allowed.") ;
944 return false;
945 }
946
947 QString curSubResource = res->defaultSubResource();
948 QString curSubResTitle = curSubResource;
949 if (res->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps) {
950 QString t = res->subResourceProperty(curSubResource, KLFLibResourceEngine::SubResPropTitle).toString();
951 if (!t.isEmpty())
952 curSubResTitle = t;
953 }
954
955 // remove the current sub-resource: first ask user confirmation
956
957 QMessageBox::StandardButton btn =
958 QMessageBox::question(this, tr("Delete Sub-Resource", "[[msgbox title]]"),
959 tr("Do you really want to delete the sub-resource <b>%1</b>, "
960 "with all its contents, from resource <b>%2</b>?")
961 .arg(curSubResTitle, displayTitle(res)),
962 QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Cancel);
963 if (btn != QMessageBox::Yes)
964 return false;
965
966 // now remove that sub-resource
967 bool result = res->deleteSubResource(curSubResource);
968
969 if (!result) {
970 // report failure
971 QMessageBox::critical(this, tr("Delete Sub-Resource", "[[msgbox title]]"),
972 tr("Deleting sub-resource failed."));
973 return false;
974 }
975
976 // close the corresponding tab.
977 slotResourceClose(viewc, true);
978 return true;
979 }
980
slotResourceOpen()981 bool KLFLibBrowser::slotResourceOpen()
982 {
983 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
984
985 QUrl url = KLFLibOpenResourceDlg::queryOpenResource(QUrl(), this);
986 if (url.isEmpty())
987 return false;
988 bool r = openResource(url);
989 if ( ! r ) {
990 QMessageBox::critical(this, tr("Error"), tr("Failed to open library resource `%1'!")
991 .arg(url.toString()));
992 }
993 return r;
994 }
995
slotResourceOpenExampleLibrary()996 bool KLFLibBrowser::slotResourceOpenExampleLibrary()
997 {
998 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
999
1000 QString importfname = QLatin1String(":/data/defaultlibrary.klf");
1001 QUrl importliburl = QUrl::fromLocalFile(importfname);
1002 QString scheme = KLFLibBasicWidgetFactory::guessLocalFileScheme(importfname);
1003 if (scheme.isEmpty()) {
1004 // assume .klf if not able to guess
1005 scheme = "klf+legacy";
1006 }
1007 importliburl.setScheme(scheme);
1008 QUrlQuery importliburlq(importliburl);
1009 importliburlq.addQueryItem("klfReadOnly", "true");
1010 importliburlq.addQueryItem("klfDefaultSubResource", "Archive");
1011 importliburl.setQuery(importliburlq);
1012
1013 bool r = openResource(importliburl, NoChangeFlag, "default");
1014 if (! r ) {
1015 QMessageBox::critical(this, tr("Error"), tr("Failed to open library resource `%1'!")
1016 .arg(importliburl.toString()));
1017 }
1018 return r;
1019 }
1020
slotResourceNew()1021 bool KLFLibBrowser::slotResourceNew()
1022 {
1023 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1024
1025 KLFLibResourceEngine *resource = KLFLibCreateResourceDlg::createResource(QString(), this, this);
1026 if (resource == NULL)
1027 return false;
1028
1029 return openResource(resource);
1030 }
1031
slotResourceSaveTo()1032 bool KLFLibBrowser::slotResourceSaveTo()
1033 {
1034 return false;
1035 // YET TO BE IMPLEMENTED... using the factories to get a save to... widget..
1036 // KLFLibBrowserViewContainer *view = curView();
1037 // if (view == NULL) {
1038 // qWarning("KLFLibBrowser::slotResourceProperties: NULL View!");
1039 // return false;
1040 // }
1041 }
1042
slotResourceDataChanged(const QList<KLFLib::entryId> &)1043 void KLFLibBrowser::slotResourceDataChanged(const QList<KLFLib::entryId>& /*entryIdList*/)
1044 {
1045 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1046
1047 // KLFLibResourceEngine *resource = qobject_cast<KLFLibResourceEngine*>(sender());
1048 // if (resource == NULL) {
1049 // qWarning("KLFLibBrowser::slotResourceDataChanged: NULL sender or not resource!");
1050 // return;
1051 // }
1052 KLFLibBrowserViewContainer *viewc = qobject_cast<KLFLibBrowserViewContainer*>(sender());
1053 if (viewc == NULL) {
1054 qWarning()<<"KLFLibBrowser::slotResourceDataChanged: NULL sender or not KLFLibBro.ViewCont.!";
1055 return;
1056 }
1057 slotRefreshResourceActionsEnabled();
1058
1059 KLFAbstractLibView * view = viewc->view();
1060 if (view == NULL) {
1061 qWarning()<<"KLFLibBrowser::slotResourceDataChanged: NULL view !!";
1062 return;
1063 }
1064 slotEntriesSelected(view->selectedEntries());
1065 }
slotResourcePropertyChanged(int propId)1066 void KLFLibBrowser::slotResourcePropertyChanged(int propId)
1067 {
1068 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1069
1070 KLFLibResourceEngine *resource = qobject_cast<KLFLibResourceEngine*>(sender());
1071 if (resource == NULL) {
1072 qWarning("KLFLibBrowser::slotResourcePropertyChanged: NULL sender or not resource!");
1073 return;
1074 }
1075 slotUpdateForResourceProperty(resource, propId);
1076 }
1077
slotUpdateForResourceProperty(KLFLibResourceEngine * resource,int propId)1078 void KLFLibBrowser::slotUpdateForResourceProperty(KLFLibResourceEngine *resource, int propId)
1079 {
1080 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1081 klfDbg("res="<<resource<<", propId="<<propId) ;
1082
1083 slotRefreshResourceActionsEnabled();
1084
1085 KLFLibBrowserViewContainer *view = findOpenResource(resource);
1086 if (view == NULL) {
1087 qWarning()<<"KLFLibBrowser::slotResourcePropertyChanged: can't find view for resource "
1088 <<resource<<", url="<<resource->url()<<"!";
1089 return;
1090 }
1091 if (propId == KLFLibResourceEngine::PropTitle || propId == KLFLibResourceEngine::PropLocked) {
1092 // the title is also affected by the locked state (# in front
1093 u->tabResources->setTabText(u->tabResources->indexOf(view), displayTitle(resource));
1094 }
1095 if (propId == KLFLibResourceEngine::PropLocked) {
1096 u->tabResources->refreshTabReadOnly(u->tabResources->indexOf(view),
1097 !resource->canModifyData(KLFLibResourceEngine::AllActionsData));
1098 u->wEntryEditor
1099 ->setInputEnabled(resource->canModifyData(KLFLibResourceEngine::ChangeData));
1100 u->wEntryEditor->displayEntries(view->view()->selectedEntries());
1101 }
1102 }
1103
slotSubResourcePropertyChanged(const QString & subResource,int propId)1104 void KLFLibBrowser::slotSubResourcePropertyChanged(const QString& subResource, int propId)
1105 {
1106 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1107 Q_UNUSED(subResource) ;
1108 klfDbg("subResource="<<subResource<<", propId="<<propId) ;
1109
1110 KLFLibResourceEngine *resource = qobject_cast<KLFLibResourceEngine*>(sender());
1111 if (resource == NULL) {
1112 qWarning("KLFLibBrowser::slotSubResourcePropertyChanged: NULL sender or not resource!");
1113 return;
1114 }
1115
1116 /** \todo ......... CHECK that subResource is our current sub-resource */
1117
1118 if (propId < 0 || propId == KLFLibResourceEngine::SubResPropTitle) {
1119 // fake a resource property title change (updated stuff is the same)
1120 slotUpdateForResourceProperty(resource, KLFLibResourceEngine::PropTitle);
1121 }
1122 if (propId < 0 || propId == KLFLibResourceEngine::SubResPropLocked) {
1123 // fake a resource property locked state change (updated stuff is the same)
1124 slotUpdateForResourceProperty(resource, KLFLibResourceEngine::PropLocked);
1125 }
1126 }
1127
slotDefaultSubResourceChanged(const QString & subResource)1128 void KLFLibBrowser::slotDefaultSubResourceChanged(const QString& subResource)
1129 {
1130 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1131 Q_UNUSED(subResource) ;
1132 klfDbg("subResource="<<subResource) ;
1133
1134 KLFLibResourceEngine *resource = qobject_cast<KLFLibResourceEngine*>(sender());
1135 if (resource == NULL) {
1136 qWarning("KLFLibBrowser::slotDefaultSubResourceChanged: NULL sender or not resource!");
1137 return;
1138 }
1139 // view already does a full refresh. We will just refresh the tab title.
1140 // fake a resource property title/locked state change (updated stuff is the same)
1141 slotUpdateForResourceProperty(resource, KLFLibResourceEngine::PropTitle);
1142 slotUpdateForResourceProperty(resource, KLFLibResourceEngine::PropLocked);
1143 }
1144
1145
slotRestoreWithStyle()1146 void KLFLibBrowser::slotRestoreWithStyle()
1147 {
1148 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1149
1150 KLFAbstractLibView * view = curLibView();
1151 if ( view == NULL )
1152 return;
1153 view->restoreWithStyle();
1154 }
1155
slotRestoreLatexOnly()1156 void KLFLibBrowser::slotRestoreLatexOnly()
1157 {
1158 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1159
1160 KLFAbstractLibView * view = curLibView();
1161 if ( view == NULL )
1162 return;
1163 view->restoreLatexOnly();
1164 }
1165
slotDeleteSelected()1166 void KLFLibBrowser::slotDeleteSelected()
1167 {
1168 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1169
1170 KLFAbstractLibView * view = curLibView();
1171 if ( view == NULL )
1172 return;
1173 KLFLibResourceEngine * resource = view->resourceEngine();
1174 if ( !resource->canModifyData(KLFLibResourceEngine::DeleteData) )
1175 return;
1176
1177 QList<KLFLib::entryId> sel = view->selectedEntryIds();
1178 klfDbg("selected "<<sel.size()<<" items:" <<sel);
1179
1180 if (sel.isEmpty())
1181 return;
1182
1183 QMessageBox::StandardButton res
1184 = QMessageBox::question(this, tr("Delete?"),
1185 tr("Delete %n selected item(s) from resource \"%1\"?", "", sel.size())
1186 .arg(resource->title()),
1187 QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Cancel);
1188 if (res != QMessageBox::Yes)
1189 return; // abort action
1190
1191 resource->deleteEntries(sel);
1192 }
1193
slotRefreshResourceActionsEnabled()1194 void KLFLibBrowser::slotRefreshResourceActionsEnabled()
1195 {
1196 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1197
1198 bool master = false;
1199 bool canrename = false;
1200 bool canrenamesubres = false;
1201 bool cansaveto = false;
1202 bool cannewsubres = false;
1203 bool candelsubres = false;
1204 uint resrolefl = 0;
1205 uint resfeatureflags = 0;
1206
1207 KLFLibBrowserViewContainer * view = curView();
1208 if ( view != NULL ) {
1209 master = true;
1210 KLFLibResourceEngine *res = view->resourceEngine();
1211 canrename = res->canModifyProp(KLFLibResourceEngine::PropTitle);
1212 resfeatureflags = res->supportedFeatureFlags();
1213 cansaveto = (resfeatureflags & KLFLibResourceEngine::FeatureSaveTo);
1214 resrolefl = view->resourceRoleFlags();
1215 cannewsubres = (resfeatureflags & KLFLibResourceEngine::FeatureSubResources) &&
1216 (res->canCreateSubResource());
1217 candelsubres = (resfeatureflags & KLFLibResourceEngine::FeatureSubResources) &&
1218 res->canDeleteSubResource(res->defaultSubResource()) ;
1219 canrenamesubres = (resfeatureflags & KLFLibResourceEngine::FeatureSubResources) &&
1220 (resfeatureflags & KLFLibResourceEngine::FeatureSubResourceProps) &&
1221 res->canModifySubResourceProperty(res->defaultSubResource(),
1222 KLFLibResourceEngine::SubResPropTitle) ;
1223 }
1224
1225 u->aRename->setEnabled(canrename);
1226 u->aRenameSubRes->setEnabled(canrenamesubres);
1227 u->aProperties->setEnabled(master);
1228 u->aNewSubRes->setEnabled(master && cannewsubres);
1229 u->aDelSubRes->setEnabled(master && candelsubres);
1230 u->aSaveTo->setEnabled(master && cansaveto);
1231 u->aNew->setEnabled(true);
1232 u->aOpen->setEnabled(true);
1233 u->aClose->setEnabled(master && !(resrolefl & NoCloseRoleFlag));
1234 }
1235
1236
1237
slotEntriesSelected(const KLFLibEntryList & entries)1238 void KLFLibBrowser::slotEntriesSelected(const KLFLibEntryList& entries)
1239 {
1240 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1241 klfDbg( "(): "<<entries ) ;
1242 if (entries.size() >= 1) {
1243 klfDbg( "Tag of first selected entry="<<entries[0].property(KLFLibEntry::Tags) ) ;
1244 }
1245
1246 KLFAbstractLibView *view = curLibView();
1247 if (view != NULL) {
1248 u->wEntryEditor
1249 ->setInputEnabled(view->resourceEngine()->canModifyData(KLFLibResourceEngine::ChangeData));
1250 }
1251
1252 u->wEntryEditor->displayEntries(entries);
1253
1254 u->btnDelete->setEnabled(entries.size() > 0);
1255 u->aDelete->setEnabled(u->btnDelete->isEnabled());
1256 u->btnRestore->setEnabled(entries.size() == 1);
1257
1258 emit libEntriesSelected(entries);
1259 }
1260
slotAddCategorySuggestions(const QStringList & catlist)1261 void KLFLibBrowser::slotAddCategorySuggestions(const QStringList& catlist)
1262 {
1263 klfDbg( "KLFLibBrowser: got category suggestions: "<<catlist ) ;
1264 u->wEntryEditor->addCategorySuggestions(catlist);
1265 }
1266
slotShowContextMenu(const QPoint & pos)1267 void KLFLibBrowser::slotShowContextMenu(const QPoint& pos)
1268 {
1269 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1270
1271 KLFAbstractLibView * view = curLibView();
1272 if ( view == NULL )
1273 return;
1274
1275 QMenu *menu = new QMenu(view);
1276
1277 QAction *a1 = menu->addAction(QIcon(":/pics/restoreall.png"), tr("Restore latex formula and style"),
1278 view, SLOT(restoreWithStyle()));
1279 QAction *a2 = menu->addAction(QIcon(":/pics/restore.png"), tr("Restore latex formula only"),
1280 view, SLOT(restoreLatexOnly()));
1281 menu->addSeparator();
1282 // NOTE: the QKeySequences given here are only for display in the context menu. Their functionality
1283 // is due to additional QShortcuts declared in the constructor. (!) (reason: these actions are
1284 // short-lived, and having global actions would require keeping their enabled status up-to-date
1285 // + we want to add view-given context menu actions dynamically)
1286 QAction *acut = menu->addAction(QIcon(":/pics/cut.png"), tr("Cut"), this, SLOT(slotCut()),
1287 QKeySequence::Cut);
1288 QAction *acopy = menu->addAction(QIcon(":/pics/copy.png"), tr("Copy"), this, SLOT(slotCopy()),
1289 QKeySequence::Copy);
1290 QAction *apaste = menu->addAction(QIcon(":/pics/paste.png"), tr("Paste"), this, SLOT(slotPaste()),
1291 QKeySequence::Paste);
1292 menu->addSeparator();
1293 QAction *adel = menu->addAction(QIcon(":/pics/delete.png"), tr("Delete from library"),
1294 this, SLOT(slotDeleteSelected()), QKeySequence::Delete);
1295 menu->addSeparator();
1296
1297 QMenu *copytomenu = new QMenu(menu);
1298 QMenu *movetomenu = new QMenu(menu);
1299 int k;
1300 QAction *acopythere, *amovethere;
1301 int n_destinations = 0;
1302 for (k = 0; k < pLibViews.size(); ++k) {
1303 if (pLibViews[k]->url() == view->url()) // skip this view
1304 continue;
1305 KLFLibResourceEngine *res = pLibViews[k]->resourceEngine();
1306 QUrl viewurl = pLibViews[k]->url();
1307 n_destinations++;
1308 acopythere = copytomenu->addAction(displayTitle(res), this, SLOT(slotCopyToResource()));
1309 acopythere->setProperty("resourceViewUrl", viewurl);
1310 amovethere = movetomenu->addAction(displayTitle(res), this, SLOT(slotMoveToResource()));
1311 amovethere->setProperty("resourceViewUrl", viewurl);
1312 if (!res->canModifyData(KLFLibResourceEngine::InsertData)) {
1313 acopythere->setEnabled(false);
1314 amovethere->setEnabled(false);
1315 }
1316 }
1317 QAction *acopyto = menu->addMenu(copytomenu);
1318 acopyto->setText(tr("Copy to"));
1319 acopyto->setIcon(QIcon(":/pics/copy.png"));
1320 QAction *amoveto = menu->addMenu(movetomenu);
1321 amoveto->setText(tr("Move to"));
1322 amoveto->setIcon(QIcon(":/pics/move.png"));
1323
1324 menu->addSeparator();
1325 menu->addMenu(pResourceMenu);
1326
1327 // Needed for when user pops up a menu without selection (ie. short list, free white space under)
1328 KLFLibEntryList selected = view->selectedEntries();
1329 bool cancopy = (selected.size() > 0) && n_destinations;
1330 bool canre = (selected.size() == 1);
1331 bool candel = view->resourceEngine()->canModifyData(KLFLibResourceEngine::DeleteData);
1332 bool canpaste = KLFAbstractLibEntryMimeEncoder::canDecodeMimeData(QApplication::clipboard()->mimeData());
1333 a1->setEnabled(canre);
1334 a2->setEnabled(canre);
1335 adel->setEnabled(candel && selected.size());
1336 acut->setEnabled(cancopy && candel);
1337 acopy->setEnabled(cancopy);
1338 apaste->setEnabled(canpaste);
1339 acopyto->setEnabled(cancopy);
1340 amoveto->setEnabled(cancopy && candel);
1341
1342 // add view's own actions
1343
1344 QList<QAction*> viewActions = view->addContextMenuActions(pos);
1345 if (viewActions.size())
1346 menu->addSeparator(); // separate view's menu items from ours
1347 for (k = 0; k < viewActions.size(); ++k) {
1348 klfDbg( "Added action "<<k<<": "<<viewActions[k] ) ;
1349 menu->addAction(viewActions[k]);
1350 }
1351
1352 menu->popup(view->mapToGlobal(pos));
1353 }
1354
1355
1356
slotMetaInfoChanged(const QMap<int,QVariant> & props)1357 void KLFLibBrowser::slotMetaInfoChanged(const QMap<int,QVariant>& props)
1358 {
1359 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1360
1361 QWidget *w = u->tabResources->currentWidget();
1362 KLFLibBrowserViewContainer *wviewc = qobject_cast<KLFLibBrowserViewContainer*>(w);
1363 if (wviewc == NULL) {
1364 qWarning("Current view is not a KLFLibBrowserViewContainer or no current tab widget!");
1365 return;
1366 }
1367 if (props.isEmpty()) {
1368 klfDbg("no changes!");
1369 return;
1370 }
1371 KLFAbstractLibView * wview = wviewc->view();
1372 if ( wview == NULL )
1373 return;
1374 QList<KLFLib::entryId> selected = wview->selectedEntryIds();
1375 KLFLibResourceEngine *resource = wview->resourceEngine();
1376 QList<int> keys = props.keys();
1377 QList<QVariant> values;
1378 int k;
1379 for (k = 0; k < keys.size(); ++k)
1380 values << props[keys[k]];
1381 bool r = resource->changeEntries(selected, keys, values);
1382 if ( ! r ) {
1383 QMessageBox::warning(this, tr("Error"),
1384 tr("Failed to write meta-information!"));
1385 // and refresh display
1386 slotEntriesSelected(wview->selectedEntries());
1387 return;
1388 }
1389
1390 // ensure that exactly the modified items are selected, as view's refresh mechanism does
1391 // not garantee to preserve selection
1392 wview->selectEntries(selected);
1393
1394 // if we categorized/tagged a formula in the history resource, copy it to the archive if the relevant
1395 // setting is enabled
1396 if (klfconfig.LibraryBrowser.historyTagCopyToArchive && !props.isEmpty()) {
1397 KLFLibBrowserViewContainer *vHistory = findSpecialResource(HistoryRoleFlag);
1398 KLFLibBrowserViewContainer *vArchive = findSpecialResource(ArchiveRoleFlag);
1399 klfDbg("vHistory="<<vHistory<<", vArchive="<<vArchive<<", wviewc="<<wviewc) ;
1400 if (vHistory != NULL && vArchive != NULL && vHistory != vArchive &&
1401 vHistory == wviewc) {
1402 klfDbg("categorized formula in history. copying it to archive");
1403 // copy the formula from history to archive
1404 KLFLibEntryList entryList = wview->selectedEntries();
1405 if (entryList.isEmpty()) {
1406 qWarning()<<KLF_FUNC_NAME<<": no selected entries ?!?";
1407 } else {
1408 KLFAbstractLibView *archiveView = vArchive->view();
1409 KLFLibResourceEngine *archiveRes = vArchive->resourceEngine();
1410 if (archiveRes == NULL || archiveView == NULL) {
1411 qWarning()<<KLF_FUNC_NAME<<": archiveRes or archiveView is NULL ?!?";
1412 } else {
1413 QList<KLFLib::entryId> insertedIds = archiveRes->insertEntries(entryList);
1414 if (!insertedIds.size() || insertedIds.contains(-1)) {
1415 QMessageBox::critical(this, tr("Error"), tr("Error copying the given items to the archive!"));
1416 } else {
1417 u->tabResources->setCurrentWidget(vArchive);
1418 // and select those items in archive that were inserted.
1419 archiveView->selectEntries(insertedIds);
1420 }
1421 }
1422 }
1423 }
1424 }
1425 }
1426
slotCopyToResource()1427 void KLFLibBrowser::slotCopyToResource()
1428 {
1429 slotCopyMoveToResource(sender(), false);
1430 }
1431
slotMoveToResource()1432 void KLFLibBrowser::slotMoveToResource()
1433 {
1434 slotCopyMoveToResource(sender(), true);
1435 }
1436
slotCopyMoveToResource(QObject * action,bool move)1437 void KLFLibBrowser::slotCopyMoveToResource(QObject *action, bool move)
1438 {
1439 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1440
1441 QUrl destUrl = action->property("resourceViewUrl").toUrl();
1442 if (destUrl.isEmpty()) {
1443 qWarning()<<"KLFLibBrowser::slotCopyMoveToResource(): bad sender property ! sender is a `"
1444 <<action->metaObject()->className()<<"'; expected QAction with 'resourceViewUrl' property set.";
1445 return;
1446 }
1447 KLFAbstractLibView *sourceView = curLibView();
1448 if (sourceView == NULL) {
1449 qWarning()<<"KLFLibBrowser::slotCopyMoveToResource(): source view is NULL!";
1450 return;
1451 }
1452 KLFLibBrowserViewContainer *destViewC = findOpenUrl(destUrl);
1453 if (destViewC == NULL || destViewC->view() == NULL) {
1454 qWarning()<<"KLFLibBrowser::slotCopyMoveToResource(): can't find dest view url for URL="<<destUrl<<" !";
1455 return;
1456 }
1457 KLFAbstractLibView *destView = destViewC->view();
1458 // now do the copy/move:
1459 slotCopyMoveToResource(destView, sourceView, move);
1460 }
1461
slotCopyMoveToResource(KLFAbstractLibView * dest,KLFAbstractLibView * source,bool move)1462 void KLFLibBrowser::slotCopyMoveToResource(KLFAbstractLibView *dest, KLFAbstractLibView *source,
1463 bool move)
1464 {
1465 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1466
1467 QList<KLFLib::entryId> selectedids = source->selectedEntryIds();
1468 KLFLibEntryList items = source->selectedEntries();
1469
1470 QList<int> inserted = dest->resourceEngine()->insertEntries(items);
1471 if ( inserted.isEmpty() || inserted.contains(-1) ) {
1472 QString msg = move ? tr("Failed to move the selected items.")
1473 : tr("Failed to copy the selected items.");
1474 QMessageBox::critical(this, tr("Error"), msg, QMessageBox::Ok, QMessageBox::Ok);
1475 return;
1476 }
1477 if (move)
1478 source->resourceEngine()->deleteEntries(selectedids);
1479 }
1480
slotCut()1481 void KLFLibBrowser::slotCut()
1482 {
1483 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1484
1485 KLFAbstractLibView * view = curLibView();
1486 if ( view == NULL )
1487 return;
1488 if ( view->selectedEntries().size() == 0 ||
1489 !view->resourceEngine()->canModifyData(KLFLibResourceEngine::DeleteData) )
1490 return;
1491
1492 QList<KLFLib::entryId> selected = view->selectedEntryIds();
1493 slotCopy();
1494 view->resourceEngine()->deleteEntries(selected);
1495 }
slotCopy()1496 void KLFLibBrowser::slotCopy()
1497 {
1498 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1499
1500 // first determine who had widget focus
1501 QWidget *focusWidget = QApplication::focusWidget();
1502 if (u->wEntryEditor->isAncestorOf(focusWidget)) {
1503 u->wEntryEditor->slotCopy();
1504 return;
1505 }
1506
1507 // otherwise perform the copy from the visible lib view
1508
1509 KLFAbstractLibView * view = curLibView();
1510 if ( view == NULL )
1511 return;
1512 if ( view->selectedEntries().size() == 0 )
1513 return;
1514
1515 KLFLibEntryList elist = view->selectedEntries();
1516 QVariantMap vprops;
1517 vprops["Url"] = view->url(); // originating URL
1518
1519 QMimeData *mimeData = KLFAbstractLibEntryMimeEncoder::createMimeData(elist, vprops);
1520 QApplication::clipboard()->setMimeData(mimeData);
1521 }
slotPaste()1522 void KLFLibBrowser::slotPaste()
1523 {
1524 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1525
1526 KLFAbstractLibView * view = curLibView();
1527 if ( view == NULL )
1528 return;
1529
1530 KLFLibEntryList elist;
1531 QVariantMap vprops;
1532
1533 const QMimeData* mimeData = QApplication::clipboard()->mimeData();
1534 bool result =
1535 KLFAbstractLibEntryMimeEncoder::decodeMimeData(mimeData, &elist, &vprops);
1536 if (!result) {
1537 QMessageBox::critical(this, tr("Error"), tr("The clipboard doesn't contain any appropriate data."));
1538 return;
1539 }
1540
1541 klfDbg( ": Pasting data! props="<<vprops ) ;
1542 QList<KLFLib::entryId> inserted = view->resourceEngine()->insertEntries(elist);
1543 if (inserted.isEmpty() || inserted.contains(-1)) {
1544 QMessageBox::critical(this, tr("Error"), tr("Error pasting items"));
1545 }
1546 }
1547
1548
slotOpenAll()1549 void KLFLibBrowser::slotOpenAll()
1550 {
1551 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1552
1553 QStringList exportFilterList;
1554 QStringList filterlist;
1555 QString exportFilter;
1556 QList<KLFLibBasicWidgetFactory::LocalFileType> locfiletypes = KLFLibBasicWidgetFactory::localFileTypes();
1557 int k;
1558 for (k = 0; k < locfiletypes.size(); ++k) {
1559 exportFilterList << locfiletypes[k].filter;
1560 filterlist << locfiletypes[k].filepattern;
1561 }
1562 exportFilterList.prepend(tr("All Known Library Files (%1)").arg(filterlist.join(" ")));
1563 exportFilterList << tr("All Files (*)");
1564 exportFilter = exportFilterList.join(";;");
1565 QString selectedFilter;
1566 QString dir = klfconfig.LibraryBrowser.lastFileDialogPath;
1567 QString fn = QFileDialog::getOpenFileName(this, tr("Open Library File"), dir, exportFilter, &selectedFilter);
1568 if (fn.isEmpty())
1569 return;
1570
1571 klfconfig.LibraryBrowser.lastFileDialogPath = QFileInfo(fn).absolutePath();
1572
1573 int ifilter = exportFilterList.indexOf(selectedFilter);
1574 ifilter--; // index in locfiletypes now
1575 QString selectedScheme;
1576 if (ifilter >= 0 && ifilter < locfiletypes.size()) {
1577 selectedScheme = locfiletypes[ifilter].scheme;
1578 } else {
1579 selectedScheme = KLFLibBasicWidgetFactory::guessLocalFileScheme(fn);
1580 }
1581 if (!QFileInfo(fn).isReadable()) {
1582 qWarning()<<KLF_FUNC_NAME<<": The given file name is not readable: "<<fn;
1583 QMessageBox::critical(this, tr("Error"), tr("The given file cannot be read: %1").arg(fn));
1584 return;
1585 }
1586 if (selectedScheme.isEmpty()) {
1587 QMessageBox::critical(this, tr("Error"), tr("Unknown open file scheme!"));
1588 return;
1589 }
1590
1591 QUrl baseUrl = QUrl::fromLocalFile(fn);
1592 baseUrl.setScheme(selectedScheme);
1593 QStringList subreslist = KLFLibEngineFactory::listSubResources(baseUrl);
1594 for (k = 0; k < subreslist.size(); ++k) {
1595 QUrl url = baseUrl;
1596 QUrlQuery urlq(url);
1597 urlq.addQueryItem("klfDefaultSubResource", subreslist[k]);
1598 url.setQuery(urlq);
1599 bool r = openResource(url);
1600 if ( !r )
1601 QMessageBox::critical(this, tr("Error"), tr("Failed to open resource %1!").arg(url.toString()));
1602 }
1603 }
1604
slotExport()1605 bool KLFLibBrowser::slotExport()
1606 {
1607 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
1608
1609 QList<QUrl> exportUrls;
1610 KLFLibResourceEngine *exportRes = KLFLibExportDialog::showExportDialogCreateResource(this, &exportUrls);
1611 if (exportRes == NULL) {
1612 return false;
1613 }
1614 exportRes->setTitle(tr("Export %1").arg(QDateTime::currentDateTime()
1615 .toString(Qt::DefaultLocaleShortDate)));
1616
1617 klfDbg("Export: to resource "<<exportRes->url().toString()<<". Export: "<<exportUrls);
1618
1619 // visual feedback for export
1620 KLFProgressDialog pdlg(QString(), this);
1621 connect(exportRes, SIGNAL(operationStartReportingProgress(KLFProgressReporter *,
1622 const QString&)),
1623 &pdlg, SLOT(startReportingProgress(KLFProgressReporter *)));
1624 pdlg.setAutoClose(false);
1625 pdlg.setAutoReset(false);
1626
1627 bool fail = false;
1628 QStringList subresources;
1629 int k;
1630 for (k = 0; k < exportUrls.size(); ++k) {
1631 klfDbg("Exporting "<<exportUrls[k]<<" ...");
1632 QUrl u = exportUrls[k];
1633 QUrlQuery uq(u);
1634 QString usr = uq.hasQueryItem("klfDefaultSubResource")
1635 ? uq.queryItemValue("klfDefaultSubResource")
1636 : QString();
1637 QString sr = usr;
1638 if (usr.isEmpty()) {
1639 // the resource doesn't support sub-resources
1640 usr = u.path().section('/', -1, -1, QString::SectionSkipEmpty); // last path element
1641 }
1642 usr.replace(QRegExp("[^a-zA-Z0-9_-]"), "_");
1643 QString subres = usr;
1644 int counter = 1;
1645 while (subresources.contains(subres))
1646 subres = usr+"_"+QString::number(counter++);
1647 // subres is the name of the subresource we will create
1648 bool r = exportRes->createSubResource(subres);
1649 if (!r) {
1650 fail = true;
1651 qWarning()<<KLF_FUNC_NAME<<" exporting "<<u<<" failed: can't create sub-resource "<<subres<<"!";
1652 continue;
1653 }
1654 subresources.append(subres);
1655 KLFLibResourceEngine *res = getOpenResource(u);
1656 if (res == NULL) {
1657 fail = true;
1658 qWarning()<<KLF_FUNC_NAME<<" can't find open resource="<<u<<" !";
1659 continue;
1660 }
1661 QString title;
1662 if (usr.isEmpty()) {
1663 title = res->title();
1664 } else {
1665 if (res->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps) {
1666 title = res->title() + ": " +
1667 res->subResourceProperty(usr, KLFLibResourceEngine::SubResPropTitle).toString();
1668 } else {
1669 title = res->title() + ": " + usr;
1670 }
1671 }
1672 exportRes->setSubResourceProperty(subres, KLFLibResourceEngine::SubResPropTitle, title);
1673
1674 pdlg.setDescriptiveText(tr("Exporting ... %3 (%1/%2)")
1675 .arg(k+1).arg(exportUrls.size()).arg(title));
1676
1677 QList<KLFLibResourceEngine::KLFLibEntryWithId> elistwid = res->allEntries(usr);
1678 /** \bug ....... Add a 'KLFLibEntryList KLFLibResourceEngine::entryList(idList)'
1679 * function so that we don't have to manually get rid of ID's ! */
1680 KLFLibEntryList elist;
1681 int j;
1682 for (j = 0; j < elistwid.size(); ++j)
1683 elist << elistwid[j].entry;
1684
1685 QList<KLFLib::entryId> insertedIds = exportRes->insertEntries(subres, elist);
1686 if (!insertedIds.size() || insertedIds.contains(-1)) {
1687 QMessageBox::critical(this, tr("Error"), tr("Error exporting items!"));
1688 }
1689 }
1690
1691 // remove our dummy sub-resource that was created with the resource
1692 // name was set in klflibbrowser_p.h: KLFLibExportDialog::showExportDi...()
1693 exportRes->deleteSubResource(QLatin1String("export_xtra"));
1694
1695 // important, as it will cause save() to be called on legacy engines, otherwise we will just
1696 // have a zombie resource waiting for something
1697 delete exportRes;
1698
1699 return !fail;
1700 }
1701
slotExportSelection()1702 bool KLFLibBrowser::slotExportSelection()
1703 {
1704 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
1705
1706 // need to fetch selection from current view
1707 KLFAbstractLibView *view = curLibView();
1708 if (view == NULL) {
1709 qWarning("KLFLibBrowser::slotResourceProperties: NULL View!");
1710 return false;
1711 }
1712
1713 // select and open target file
1714 KLFLibEngineFactory *factory = KLFLibLegacyEngineFactory::findFactoryFor("klf+legacy");
1715 if (factory == NULL) {
1716 qWarning()<<KLF_FUNC_NAME<<": Can't create KLFLibLegacyEngineFactory object (\"klf+legacy\") ?!?";
1717 return false;
1718 }
1719 QString filter = factory->schemeTitle(QLatin1String("klf+legacy")) + " (*.klf)";
1720 QString path = klfconfig.LibraryBrowser.lastFileDialogPath;
1721 QString fileName = QFileDialog::getSaveFileName(this, tr("Export selection to file..."), path, filter);
1722
1723 if (fileName.isEmpty()) {
1724 klfDbg("Canceled by user.");
1725 return false;
1726 }
1727
1728 if (QFile::exists(fileName)) {
1729 // erase it. the file dialog already asked for overwrite confirmation.
1730 if ( ! QFile::remove(fileName) ) {
1731 QMessageBox::critical(this, tr("Error"), tr("Failed to overwrite file %1").arg(fileName));
1732 qWarning()<<KLF_FUNC_NAME<<": Can't overwrite file "<<fileName;
1733 return false;
1734 }
1735 }
1736
1737 klfDbg("Exporting to file "<<fileName);
1738
1739 // get selected entries
1740 KLFLibEntryList entryList = view->selectedEntries();
1741
1742 // create file resource
1743 KLFLibWidgetFactory::Parameters param;
1744 param["klfScheme"] = QLatin1String("klf+legacy");
1745 param["Filename"] = fileName;
1746 param["klfDefaultSubResource"] = tr("Export", "[[export selection default sub-resource name]]");
1747 KLFLibResourceEngine *resource = factory->createResource(QLatin1String("klf+legacy"), param, this);
1748
1749 if (resource == NULL) {
1750 QMessageBox::critical(this, tr("Error"), tr("Failed to create export file %1!").arg(fileName));
1751 return false;
1752 }
1753
1754 QList<KLFLib::entryId> insertedIds = resource->insertEntries(entryList);
1755 if (!insertedIds.size() || insertedIds.contains(-1)) {
1756 QMessageBox::critical(this, tr("Error"), tr("Error exporting items!"));
1757 }
1758
1759 // important, as it will cause save() to be called on legacy engines, otherwise we will just
1760 // have a zombie resource waiting for something
1761 delete resource;
1762
1763 return true;
1764 }
1765
slotStartProgress(KLFProgressReporter * progressReporter,const QString & text)1766 void KLFLibBrowser::slotStartProgress(KLFProgressReporter *progressReporter, const QString& text)
1767 {
1768 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
1769 klfDbg( ": min,max="<<progressReporter->min()<<","<<progressReporter->max()
1770 <<"; text="<<text ) ;
1771
1772 KLFProgressDialog *pdlg = new KLFProgressDialog(false, QString(), this);
1773
1774 pdlg->startReportingProgress(progressReporter, text);
1775
1776 pdlg->setProperty("klf_libbrowser_pdlg_want_hideautodelete", QVariant(true));
1777 pdlg->installEventFilter(this);
1778 }
1779
1780
1781
event(QEvent * e)1782 bool KLFLibBrowser::event(QEvent *e)
1783 {
1784 if (e->type() == QEvent::KeyPress) {
1785 QKeyEvent *ke = (QKeyEvent*)e;
1786 if (ke->key() == Qt::Key_F8 && ke->modifiers() == 0) {
1787 hide();
1788 e->accept();
1789 return true;
1790 }
1791 }
1792 return QWidget::event(e);
1793 }
1794
timerEvent(QTimerEvent * event)1795 void KLFLibBrowser::timerEvent(QTimerEvent *event)
1796 {
1797 QWidget::timerEvent(event);
1798 }
1799
1800
showEvent(QShowEvent * event)1801 void KLFLibBrowser::showEvent(QShowEvent *event)
1802 {
1803 // update some last-minute stuff
1804 // like the tab colors (which could have changed upon setting a skin)
1805 int k;
1806 for (k = 0; k < pLibViews.size(); ++k) {
1807 KLFLibBrowserViewContainer *viewc = pLibViews[k];
1808 KLFLibResourceEngine *resource = viewc->resourceEngine();
1809 u->tabResources->refreshTabReadOnly(u->tabResources->indexOf(viewc),
1810 !resource->canModifyData(KLFLibResourceEngine::AllActionsData));
1811 }
1812 u->tabResources->setFocus();
1813 // and call superclass
1814 QWidget::showEvent(event);
1815 }
1816
1817
1818