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