View Issue Details

IDProjectCategoryView StatusLast Update
0009154ScribusUser Interfacepublic2019-12-08 21:24
Reporterpygmee Assigned Toale  
PrioritynormalSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
PlatformLinuxOSDebianOS VersionLenny
Product Version 
Target VersionFixed in Version 
Summary0009154: [PATCH] Recursive search in Manage images
DescriptionWhen manage images shows missing pictures, searching the picture has to be done on each, even all the pictures are in the same directory. Scribus should list all the image of the document that were in the same directory and look for them in this new one.
TagsNo tags attached.
PatchYes

Relationships

related to 0015871 closedale pictures - path 
related to 0011776 closedale [PATCH]: Missing linked ressources improvement 

Activities

subeditor

2010-06-11 14:03

reporter   ~0024047

Sometimes image names (and even size or dimensions and other attributes) are similar in different folders, so to avoid loading wrong pictures this (useful) feature should be prompted by some warning or by checkbox in search dialog.

ale

2019-11-22 08:23

manager   ~0047112

i somehow forgot to upload the patch...

https://gitlab.com/scribus/scribus/merge_requests/13

apply-images.diff (21,314 bytes)
diff --git a/scribus/ui/picsearch.cpp b/scribus/ui/picsearch.cpp
index 7e530eb5b6df5734b9a67ddf5b1b35b26f899269..d922d64eed5e4c93aa7d9bec4089dcb1550376a8 100644
--- a/scribus/ui/picsearch.cpp
+++ b/scribus/ui/picsearch.cpp
@@ -20,7 +20,8 @@ for which a new license (GPL+exception) is in place.
 
 
 
-PicSearch::PicSearch(QWidget* parent, const QString & fileName, const QStringList & avalableFiles) : QDialog(parent), currentImage(QString())
+PicSearch::PicSearch(QWidget* parent, const QString & fileName, const QStringList & avalableFiles, bool brokenLinksOnly) :
+	QDialog(parent), brokenLinksOnly{brokenLinksOnly}
 {
 	setupUi(this);
 	setModal(true);
@@ -28,13 +29,18 @@ PicSearch::PicSearch(QWidget* parent, const QString & fileName, const QStringLis
 	previewLabel->hide();
 	fileNameLabel->setText(fileName);
 
-	for (int i = 0; i < avalableFiles.count(); ++i)
-		foundFilesBox->addItem( QDir::toNativeSeparators(avalableFiles[i]) );
+	for (const auto& file: avalableFiles)
+		foundFilesBox->addItem(QDir::toNativeSeparators(file));
+
+	foundFilesBox->setCurrentRow(0);
+
+	matchWarningLabel->setVisible(false);
 
 	// signals and slots connections
 	connect(cancelButton, SIGNAL( clicked() ), this, SLOT( reject() ) );
 	connect(useButton, SIGNAL( clicked() ), this, SLOT( accept() ) );
 	connect(previewCheckBox, SIGNAL( clicked() ), this, SLOT( previewCheckBox_clicked() ) );
+	connect(matchCheckBox, SIGNAL( clicked() ), this, SLOT( matchCheckBox_clicked() ) );
 	connect(foundFilesBox, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(foundFilesBox_clicked(QListWidgetItem*)));
 }
 
@@ -43,25 +49,28 @@ void PicSearch::previewCheckBox_clicked()
 	if (previewCheckBox->isChecked())
 	{
 		previewLabel->show();
-		if (!currentImage.isEmpty())
-			createPreview();
+		createPreview();
 	}
 	else
 		previewLabel->hide();
 }
 
+void PicSearch::matchCheckBox_clicked()
+{
+	matchWarningLabel->setVisible(brokenLinksOnly && matchCheckBox->isChecked());
+}
+
 void PicSearch::foundFilesBox_clicked(QListWidgetItem *c)
 {
 	if (c == nullptr)
 		return;
-	currentImage = QDir::fromNativeSeparators(c->text());
 	if (previewCheckBox->isChecked())
 		createPreview();
-	useButton->setEnabled(true);
 }
 
 void PicSearch::createPreview()
 {
+	const auto currentImage = foundFilesBox->currentItem()->text();
 	QPixmap pm(200, 200);
 	QFileInfo fi = QFileInfo(currentImage);
 	int w = 200;
diff --git a/scribus/ui/picsearch.h b/scribus/ui/picsearch.h
index 90eded0a84a77d3ca1ccb94fa58310d2e3cebeb6..136db135e01e90cb45d3b5435a67ee008f1b4626 100644
--- a/scribus/ui/picsearch.h
+++ b/scribus/ui/picsearch.h
@@ -24,7 +24,7 @@ for which a new license (GPL+exception) is in place.
 It's called after image search Extras/Manage Pictures/ Click [Search] button for chosen
 image frame item. */
 class SCRIBUS_API PicSearch : public QDialog, Ui::PicSearch
-{ 
+{
 	Q_OBJECT
 
 public:
@@ -35,11 +35,13 @@ public:
 	\param fileName QString name of image
 	\param avalableFiles QStringList List of Paths where an Image with the given Name is present
 	*/
-	PicSearch( QWidget* parent, const QString & fileName, const QStringList & avalableFiles);
+	PicSearch( QWidget* parent, const QString & fileName, const QStringList & avalableFiles, bool brokenLinksOnly);
 	~PicSearch() {};
 
-	//! \brief Currently selected image with its full path
-	QString currentImage;
+	//! \brief Selected image with its full path
+	QString getSelectedImage() { return foundFilesBox->currentItem()->text(); }
+	//! \brief Matching images should also be replaced?
+	bool isApplyToMatchingImages() { return matchCheckBox->isChecked(); }
 
 private slots:
 	/*!
@@ -48,6 +50,11 @@ private slots:
 	*/
 	void previewCheckBox_clicked();
 	/*!
+	\author Ale Rimoldi
+	\brief If matching is desired (checked) then show a warning when only broken linked images are matched.
+	*/
+	void matchCheckBox_clicked();
+	/*!
 	\author Franz Schmid
 	\brief When image is selected from the ListBox then the image preview may be shown and the Use button is enabled.
 	\param c QListBoxItem
@@ -63,8 +70,9 @@ signals:
 	//! \brief Emitted when the pic for a row is replaced. Arg is row index.
 	void rowPicChanged(unsigned int);
 
-protected:
+private:
 	QSize minS;
+	bool brokenLinksOnly;
 };
 
 #endif // PICSEARCH_H
diff --git a/scribus/ui/picsearch.ui b/scribus/ui/picsearch.ui
index fe1ff2445e6221bfd0b796b8e06f293fe44ab153..135b4afb9f9a737560c8c2a013c7bea89738f549 100644
--- a/scribus/ui/picsearch.ui
+++ b/scribus/ui/picsearch.ui
@@ -1,60 +1,77 @@
-<ui version="4.0" >
- <author>Petr Vanek &lt;petr@scribus.info></author>
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <author>Petr Vanek &lt;petr@scribus.info&gt;</author>
  <class>PicSearch</class>
- <widget class="QDialog" name="PicSearch" >
-  <property name="geometry" >
+ <widget class="QDialog" name="PicSearch">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>499</width>
-    <height>263</height>
+    <width>516</width>
+    <height>292</height>
    </rect>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>Result</string>
   </property>
-  <layout class="QVBoxLayout" >
-   <property name="margin" >
+  <layout class="QVBoxLayout">
+   <property name="spacing">
+    <number>5</number>
+   </property>
+   <property name="leftMargin">
     <number>10</number>
    </property>
-   <property name="spacing" >
-    <number>5</number>
+   <property name="topMargin">
+    <number>10</number>
+   </property>
+   <property name="rightMargin">
+    <number>10</number>
+   </property>
+   <property name="bottomMargin">
+    <number>10</number>
    </property>
    <item>
-    <layout class="QHBoxLayout" >
-     <property name="margin" >
+    <layout class="QHBoxLayout">
+     <property name="spacing">
+      <number>5</number>
+     </property>
+     <property name="leftMargin">
       <number>0</number>
      </property>
-     <property name="spacing" >
-      <number>5</number>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
      </property>
      <item>
-      <widget class="QLabel" name="textLabel1" >
-       <property name="text" >
+      <widget class="QLabel" name="textLabel1">
+       <property name="text">
         <string>Search Results for: </string>
        </property>
-       <property name="wordWrap" >
+       <property name="wordWrap">
         <bool>false</bool>
        </property>
       </widget>
      </item>
      <item>
-      <widget class="QLabel" name="fileNameLabel" >
-       <property name="sizePolicy" >
-        <sizepolicy>
-         <hsizetype>7</hsizetype>
-         <vsizetype>5</vsizetype>
+      <widget class="QLabel" name="fileNameLabel">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
-       <property name="frameShape" >
+       <property name="frameShape">
         <enum>QFrame::Box</enum>
        </property>
-       <property name="text" >
+       <property name="text">
         <string/>
        </property>
-       <property name="wordWrap" >
+       <property name="wordWrap">
         <bool>false</bool>
        </property>
       </widget>
@@ -62,43 +79,61 @@
     </layout>
    </item>
    <item>
-    <layout class="QHBoxLayout" >
-     <property name="margin" >
+    <layout class="QHBoxLayout">
+     <property name="spacing">
+      <number>5</number>
+     </property>
+     <property name="leftMargin">
       <number>0</number>
      </property>
-     <property name="spacing" >
-      <number>5</number>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
      </property>
      <item>
-      <widget class="QListWidget" name="foundFilesBox" />
+      <widget class="QListWidget" name="foundFilesBox"/>
      </item>
      <item>
-      <layout class="QVBoxLayout" >
-       <property name="margin" >
+      <layout class="QVBoxLayout">
+       <property name="spacing">
+        <number>5</number>
+       </property>
+       <property name="leftMargin">
         <number>0</number>
        </property>
-       <property name="spacing" >
-        <number>5</number>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
+        <number>0</number>
        </property>
        <item>
-        <widget class="QCheckBox" name="previewCheckBox" >
-         <property name="text" >
+        <widget class="QCheckBox" name="previewCheckBox">
+         <property name="text">
           <string>&amp;Preview</string>
          </property>
-         <property name="shortcut" >
+         <property name="shortcut">
           <string>Alt+P</string>
          </property>
         </widget>
        </item>
        <item>
         <spacer>
-         <property name="orientation" >
+         <property name="orientation">
           <enum>Qt::Vertical</enum>
          </property>
-         <property name="sizeType" >
+         <property name="sizeType">
           <enum>QSizePolicy::Expanding</enum>
          </property>
-         <property name="sizeHint" >
+         <property name="sizeHint" stdset="0">
           <size>
            <width>21</width>
            <height>81</height>
@@ -106,73 +141,59 @@
          </property>
         </spacer>
        </item>
-       <item>
-        <widget class="QPushButton" name="useButton" >
-         <property name="enabled" >
-          <bool>false</bool>
-         </property>
-         <property name="text" >
-          <string>&amp;Select</string>
-         </property>
-         <property name="shortcut" >
-          <string>Alt+S</string>
-         </property>
-         <property name="default" >
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QPushButton" name="cancelButton" >
-         <property name="text" >
-          <string>Cancel</string>
-         </property>
-        </widget>
-       </item>
       </layout>
      </item>
      <item>
-      <layout class="QVBoxLayout" >
-       <property name="margin" >
+      <layout class="QVBoxLayout">
+       <property name="spacing">
+        <number>5</number>
+       </property>
+       <property name="leftMargin">
         <number>0</number>
        </property>
-       <property name="spacing" >
-        <number>5</number>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
+        <number>0</number>
        </property>
        <item>
-        <widget class="QLabel" name="previewLabel" >
-         <property name="minimumSize" >
+        <widget class="QLabel" name="previewLabel">
+         <property name="minimumSize">
           <size>
            <width>210</width>
            <height>210</height>
           </size>
          </property>
-         <property name="maximumSize" >
+         <property name="maximumSize">
           <size>
            <width>210</width>
            <height>210</height>
           </size>
          </property>
-         <property name="frameShape" >
+         <property name="frameShape">
           <enum>QFrame::Box</enum>
          </property>
-         <property name="alignment" >
+         <property name="alignment">
           <set>Qt::AlignCenter</set>
          </property>
-         <property name="wordWrap" >
+         <property name="wordWrap">
           <bool>false</bool>
          </property>
         </widget>
        </item>
        <item>
         <spacer>
-         <property name="orientation" >
+         <property name="orientation">
           <enum>Qt::Vertical</enum>
          </property>
-         <property name="sizeType" >
+         <property name="sizeType">
           <enum>QSizePolicy::Expanding</enum>
          </property>
-         <property name="sizeHint" >
+         <property name="sizeHint" stdset="0">
           <size>
            <width>20</width>
            <height>40</height>
@@ -184,9 +205,78 @@
      </item>
     </layout>
    </item>
+   <item>
+    <widget class="QCheckBox" name="matchCheckBox">
+     <property name="text">
+      <string>Apply to all &amp;Matching Images</string>
+     </property>
+     <property name="shortcut">
+      <string>Alt+M</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="matchWarningLabel">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>Since you selected an image with a broken link, only image frames with invalid links will be modified.</string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="useButton">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="text">
+        <string>&amp;Select</string>
+       </property>
+       <property name="shortcut">
+        <string>Alt+S</string>
+       </property>
+       <property name="default">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cancelButton">
+       <property name="text">
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
   </layout>
  </widget>
- <layoutdefault spacing="6" margin="11" />
+ <layoutdefault spacing="6" margin="11"/>
  <resources/>
  <connections/>
 </ui>
diff --git a/scribus/ui/picsearchoptions.cpp b/scribus/ui/picsearchoptions.cpp
index fa7984306b789a0ce63cb08886561418372d3c32..a5384f622075661731c032499c8e4466d220b723 100644
--- a/scribus/ui/picsearchoptions.cpp
+++ b/scribus/ui/picsearchoptions.cpp
@@ -89,7 +89,7 @@ void PicSearchOptions::slotChangeSearchDir()
 #else 
 	// TODO: and on _WIN32 workDir is ... ?
 #endif
-	QString searchBase = QFileDialog::getExistingDirectory(this, tr("Select a base directory for search"), workDir);
+	QString searchBase = QFileDialog::getExistingDirectory(this, tr("Select a base directory to search for ") + fileEdit->text(), workDir);
 	if (searchBase.isEmpty() || !QDir().exists(searchBase))
 		return;
 	m_strLastDirSearched = searchBase;
diff --git a/scribus/ui/picstatus.cpp b/scribus/ui/picstatus.cpp
index 26c93c42bbf3c4c9557c5e112ea525064ed55da9..5926c67e201299e0d6e531f25b22446bef802166 100644
--- a/scribus/ui/picstatus.cpp
+++ b/scribus/ui/picstatus.cpp
@@ -36,8 +36,6 @@ for which a new license (GPL+exception) is in place.
 #include <QScopedPointer>
 #include <QToolButton>
 
-#include <cstdio>
-
 #include "commonstrings.h"
 #include "effectsdialog.h"
 #include "extimageprops.h"
@@ -201,14 +199,13 @@ void PicStatus::fillTable()
 
 void PicStatus::sortByName()
 {
-	QListWidgetItem *firstItem = nullptr;
 	QMap<QString, PicItem*> sorted;
 
 	int num = imageViewArea->count();
 	if (num == 0)
 		return;
 
-	firstItem = imageViewArea->currentItem();
+	auto firstItem = imageViewArea->currentItem();
 	for (int a = num-1; a > -1; --a)
 	{
 		QListWidgetItem *ite = imageViewArea->takeItem(a);
@@ -233,14 +230,13 @@ void PicStatus::sortByName()
 
 void PicStatus::sortByPage()
 {
-	QListWidgetItem *firstItem = nullptr;
 	QMap<int, PicItem*> sorted;
 
 	int num = imageViewArea->count();
 	if (num == 0)
 		return;
 
-	firstItem = imageViewArea->currentItem();
+	auto firstItem = imageViewArea->currentItem();
 	for (int a = num-1; a > -1; --a)
 	{
 		QListWidgetItem *ite = imageViewArea->takeItem(a);
@@ -446,18 +442,18 @@ void PicStatus::SelectPic()
 	emit selectElementByItem(currItem, true, 1);
 }
 
-bool PicStatus::loadPict(const QString & newFilePath)
+bool PicStatus::loadPict(PageItem* item, const QString & newFilePath)
 {
 	// Hack to fool the LoadPict function
-	currItem->Pfile = newFilePath;
-	bool masterPageMode = !currItem->OnMasterPage.isEmpty();
+	item->Pfile = newFilePath;
+	bool masterPageMode = !item->OnMasterPage.isEmpty();
 	bool oldMasterPageMode = m_Doc->masterPageMode();
 	if (masterPageMode != oldMasterPageMode)
 		m_Doc->setMasterPageMode(masterPageMode);
-	m_Doc->loadPict(newFilePath, currItem, true);
+	m_Doc->loadPict(newFilePath, item, true);
 	if (masterPageMode != oldMasterPageMode)
 		m_Doc->setMasterPageMode(oldMasterPageMode);
-	return currItem->imageIsAvailable;
+	return item->imageIsAvailable;
 }
 
 void PicStatus::SearchPic()
@@ -483,16 +479,24 @@ void PicStatus::SearchPic()
 		return;
 	}
 
-	QScopedPointer<PicSearch> dia2(new PicSearch(this, dia->getFileName(), dia->getMatches()));
+	auto item = static_cast<PicItem*>(imageViewArea->currentItem());
+	bool brokenLink = !(item->PageItemObject->imageIsAvailable);
+
+	QScopedPointer<PicSearch> dia2(new PicSearch(this, dia->getFileName(), dia->getMatches(), brokenLink));
 	if (dia2->exec() != QDialog::Accepted)
 		return;
-	Q_ASSERT(!dia2->currentImage.isEmpty());
-	loadPict(dia2->currentImage);
+
+	auto source = QFileInfo(currItem->Pfile);
+
+	loadPict(currItem, dia2->getSelectedImage());
 	refreshItem(currItem);
-	QFileInfo fi = QFileInfo(currItem->Pfile);
-	imageViewArea->currentItem()->setText(fi.fileName());
-	imageViewArea->currentItem()->setIcon(createImgIcon(currItem));
+	auto target = QFileInfo(currItem->Pfile);
+	item->setText(target.fileName());
+	item->setIcon(createImgIcon(currItem));
 	imageSelected(imageViewArea->currentItem());
+
+	if (dia2->isApplyToMatchingImages())
+		relinkMatchingImages(source, target, brokenLink);
 }
 
 void PicStatus::FileManager()
@@ -515,7 +519,7 @@ void PicStatus::doImageEffects()
 	if (dia->exec())
 	{
 		currItem->effectsInUse = dia->effectsList;
-		loadPict(currItem->Pfile);
+		loadPict(currItem, currItem->Pfile);
 		refreshItem(currItem);
 		imageViewArea->currentItem()->setIcon(createImgIcon(currItem));
 	}
@@ -530,7 +534,7 @@ void PicStatus::doImageExtProp()
 	ExtImageProps dia(this, &currItem->pixm.imgInfo, currItem, m_Doc->view());
 	if (dia.exec())
 	{
-		loadPict(currItem->Pfile);
+		loadPict(currItem, currItem->Pfile);
 		refreshItem(currItem);
 		imageViewArea->currentItem()->setIcon(createImgIcon(currItem));
 	}
@@ -543,3 +547,31 @@ void PicStatus::doEditImage()
 	SelectPic();
 	ScCore->primaryMainWindow()->callImageEditor();
 }
+
+/**
+ * Relink all matching images.
+ * Images match if they have the same path as the pattern.
+ * If the "pattern" was a broken link, only images with broken links will match.
+ */
+void PicStatus::relinkMatchingImages(const QFileInfo& source, const QFileInfo& target, bool brokenLink)
+{
+	for (int i = 0; i < imageViewArea->count(); i++)
+	{
+		auto item = static_cast<PicItem*>(imageViewArea->item(i));
+
+		if (brokenLink && item->PageItemObject->imageIsAvailable)
+			continue;
+
+		auto fi = QFileInfo(item->PageItemObject->Pfile);
+
+		if (fi.path() != source.path())
+			continue;
+		if (fi.fileName() == target.fileName())
+			continue;
+
+		loadPict(item->PageItemObject, QDir(target.path()).filePath(fi.fileName()));
+		refreshItem(item->PageItemObject);
+		item->setText(fi.fileName());
+		item->setIcon(createImgIcon(item->PageItemObject));
+	}
+}
diff --git a/scribus/ui/picstatus.h b/scribus/ui/picstatus.h
index 455e79e79818845d07b4e0a89fb5bda40cb3b954..900d5f8689d353e4830c25859cf9d164442c7bc4 100644
--- a/scribus/ui/picstatus.h
+++ b/scribus/ui/picstatus.h
@@ -11,6 +11,8 @@ for which a new license (GPL+exception) is in place.
 #include "ui_picstatus.h"
 #include <QListWidgetItem>
 
+class QFileInfo;
+
 class ScribusDoc;
 class PageItem;
 
@@ -82,6 +84,11 @@ private slots:
 	void FileManager();
 	void doImageEffects();
 	void doImageExtProp();
+	/*!
+	\author Ale Rimoldi
+	\brief Relink all images matching pattern.
+	*/
+	void relinkMatchingImages(const QFileInfo& source, const QFileInfo& target, bool brokenLink);
 	void doEditImage();
 
 signals:
@@ -96,7 +103,7 @@ protected:
 
 	/*! \brief Load the image specified into the PageItem
 	\param newFilePath a file path */
-	bool loadPict(const QString & newFilePath);
+	bool loadPict(PageItem* item, const QString & newFilePath);
 
 private:
 	ScribusDoc *m_Doc;
apply-images.diff (21,314 bytes)

ale

2019-11-22 08:33

manager   ~0047114

ah, no... the patch was already in 0011776 ...

Issue History

Date Modified Username Field Change
2010-06-09 21:17 pygmee New Issue
2010-06-11 14:03 subeditor Note Added: 0024047
2019-11-22 08:09 ale Relationship added related to 0015871
2019-11-22 08:23 ale File Added: apply-images.diff
2019-11-22 08:23 ale Note Added: 0047112
2019-11-22 08:24 ale Summary Recursive search in Manage images => [PATCH] Recursive search in Manage images
2019-11-22 08:24 ale Patch => Yes
2019-11-22 08:33 ale Relationship added related to 0011776
2019-11-22 08:33 ale Note Added: 0047114
2019-11-23 21:57 cbradney Assigned To => ale
2019-11-23 21:57 cbradney Status new => resolved
2019-11-23 21:57 cbradney Resolution open => fixed
2019-12-08 21:24 cbradney Status resolved => closed