View Issue Details

IDProjectCategoryView StatusLast Update
0017174ScribusGeneralpublic2024-03-14 16:07
Reporterale Assigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
Status newResolutionopen 
Product Version1.7.0.svn 
Summary0017174: Multiple duplicate by page: optionally adjust according to the margins
Descriptionfollowing up my comment in the forums

https://forums.scribus.net/index.php/topic,5002.msg22993.html#msg22993

i suggest that multiple duplicate by page should allow the user to adjust the position according to:
- one of left / right margin
- one of top / right margin

TagsNo tags attached.
PatchNo

Relationships

related to 0017175 new [PATCH] Multiple duplicate by page: optionally limit the number of copies 

Activities

ale

2024-03-14 07:15

manager  

duplicate-margin.png (37,396 bytes)   
duplicate-margin.png (37,396 bytes)   

ale

2024-03-14 09:44

manager   ~0051035

i'm working on a patch.

the UI is done.

i'm changing the behavior of the existing UI code (to match what the code currently supports): if the selection is on multiple pages, then only the options "following pages" will be available.
the other ones are too complex to code and also to grasp for the user.

ale

2024-03-14 10:22

manager   ~0051036

i'm also adding a maximum number of copies
duplicate-copies.png (41,798 bytes)   
duplicate-copies.png (41,798 bytes)   

ale

2024-03-14 10:52

manager   ~0051037

after having worked on this for a couple of hours, i've come to the conclusion that the patch is not really needed and the same goal can be (better) achieved with having a selection on two pages.

i'm uploading the current status of the patch (if somebody else or my future me thinks that it is worth to complete it) and continue my patch to only add the number of copies (in a different ticket)
duplicate-margins.diff (11,299 bytes)   
diff --git a/scribus/scribusdoc.cpp b/scribus/scribusdoc.cpp
index 041f139e7..77db99843 100644
--- a/scribus/scribusdoc.cpp
+++ b/scribus/scribusdoc.cpp
@@ -13789,6 +13789,7 @@ void ScribusDoc::multipleDuplicateByPage(const ItemMultipleDuplicateData& dialog
 {
 	int currPageNumber = currentPageNumber();
 	std::vector<int> pages;
+	std::unordered_map<int, std::array<double, 4>> originalPageMargins{};
 	QString pageRange;
 
 	if (!m_Selection->itemsAreOnSamePage())
@@ -13796,43 +13797,47 @@ void ScribusDoc::multipleDuplicateByPage(const ItemMultipleDuplicateData& dialog
 		int firstPage = Pages->count(), lastPage = 0;
 		for (auto item: selection.items())
 		{
-			if ((item->OwnPage >= 0) && (item->OwnPage < firstPage))
-				firstPage = item->OwnPage;
-			if ((item->OwnPage) >= 0 && (item->OwnPage > lastPage))
-				lastPage = item->OwnPage;
+			if (item->OwnPage >= 0)
+			{
+				originalPageMargins[item->OwnPage] = {0.0, 0.0, 0.0, 0.0};
+				if (item->OwnPage < firstPage)
+					firstPage = item->OwnPage;
+				if (item->OwnPage > lastPage)
+					lastPage = item->OwnPage;
+			}
 		}
 		setCurrentPage(Pages->at(firstPage));
 		int pageSpread = lastPage - firstPage + 1;
 		QStringList pageList;
+		// with multi-page selection, only "following pages" is available
+		for (int i = lastPage + 2; i < Pages->count(); i += pageSpread)
+			pageList << QString::number(i);
+		pageRange = pageList.join(',');
+	}
+	else
+	{
+		if (selection.itemAt(0)->OwnPage > 0)
+			originalPageMargins[selection.itemAt(0)->OwnPage] = {0.0, 0.0, 0.0, 0.0};
 		if (dialogData.pageSelection == 1)
-			for (int i = lastPage + 2; i < Pages->count(); i += pageSpread)
+			pageRange = QString("%1-%2").arg(currPageNumber + 2).arg(Pages->count());
+		else if ((dialogData.pageSelection == 2) || dialogData.pageSelection == 3)
+		{
+			int start = currPageNumber + 2;
+			// round to the next odd / even number
+			if (dialogData.pageSelection == 2)
+				start += start % 2;
+			else
+				start += 1 - (start % 2);
+
+			QStringList pageList;
+			for (int i = start; i <= Pages->count(); i += 2)
 				pageList << QString::number(i);
+			pageRange = pageList.join(',');
+		}
 		else if (dialogData.pageSelection == 4)
 		{
-			// TODO: what to do with manual selections?
 			pageRange = dialogData.pageRange;
 		}
-		pageRange = pageList.join(',');
-	}
-	else if (dialogData.pageSelection == 1)
-		pageRange = QString("%1-%2").arg(currPageNumber + 2).arg(Pages->count());
-	else if ((dialogData.pageSelection == 2) || dialogData.pageSelection == 3)
-	{
-		int start = currPageNumber + 2;
-		// round to the next odd / even number
-		if (dialogData.pageSelection == 2)
-			start += start % 2;
-		else
-			start += 1 - (start % 2);
-
-		QStringList pageList;
-		for (int i = start; i <= Pages->count(); i += 2)
-			pageList << QString::number(i);
-		pageRange = pageList.join(',');
-	}
-	else if (dialogData.pageSelection == 4)
-	{
-		pageRange = dialogData.pageRange;
 	}
 	parsePagesString(pageRange, &pages, Pages->count());
 
diff --git a/scribus/ui/multipleduplicate.cpp b/scribus/ui/multipleduplicate.cpp
index d569dbf0b..3f1f453ef 100644
--- a/scribus/ui/multipleduplicate.cpp
+++ b/scribus/ui/multipleduplicate.cpp
@@ -50,12 +50,57 @@ MultipleDuplicate::MultipleDuplicate(QWidget* parent, ScribusDoc *doc) : QDialog
 	{
 		radioButtonPageOdd->setEnabled(false);
 		radioButtonPageEven->setEnabled(false);
+		radioButtonPageRange->setEnabled(false);
+		lineEditPageRange->setEnabled(false);
+		toolButtonPageRange->setEnabled(false);
 	}
 	
 	createGapRadioButton->setChecked(true);
 	setCopiesGap();
 
-	toolButtonPageRange->setIcon(IconManager::instance().loadIcon("ellipsis.png"));
+	spinBoxMaxCopies->setToolTip(tr("Maximal number of duplicates to be created"));
+	spinBoxMaxCopies->setMinimum(0);
+	spinBoxMaxCopies->setSpecialValueText( tr( "Auto" ));
+	spinBoxMaxCopies->setDecimals(0);
+	spinBoxMaxCopies->setSuffix("");
+
+	{
+		auto& im = IconManager::instance();
+		toolButtonPageRange->setIcon(im.loadIcon("ellipsis.png"));
+
+		toolButtonAdjustToMarginLeft->setIcon(im.loadIcon("22/align-horizontal-left.png"));
+		toolButtonAdjustToMarginRight->setIcon(im.loadIcon("22/align-horizontal-right.png"));
+		toolButtonAdjustToMarginTop->setIcon(im.loadIcon("22/align-vertical-top.png"));
+		toolButtonAdjustToMarginBottom->setIcon(im.loadIcon("22/align-vertical-bottom.png"));
+		toolButtonAdjustToMarginLeft->setCheckable(true);
+		toolButtonAdjustToMarginRight->setCheckable(true);
+		toolButtonAdjustToMarginTop->setCheckable(true);
+		toolButtonAdjustToMarginBottom->setCheckable(true);
+
+		labelAdjustToMargin->setToolTip(tr("Adjust the position of the created item by the difference in the margins."));
+		toolButtonAdjustToMarginLeft->setToolTip(
+			doc->pagePositioning() == singlePage ?
+			tr("Adjust with left margin") :
+			tr("Adjust with inside margin")
+		);
+		toolButtonAdjustToMarginRight->setToolTip(
+			doc->pagePositioning() == singlePage ?
+			tr("Adjust with right margin") :
+			tr("Adjust with outside margin")
+		);
+		toolButtonAdjustToMarginTop->setToolTip(tr("Adjust with top margin"));
+		toolButtonAdjustToMarginBottom->setToolTip(tr("Adjust with bottom margin"));
+
+		// make the buttons exclusive in pairs, but only for the checked state
+		connect(toolButtonAdjustToMarginLeft, &QToolButton::toggled, this,
+			[&](bool checked) { if (checked) {toolButtonAdjustToMarginRight->setChecked(false);} });
+		connect(toolButtonAdjustToMarginRight, &QToolButton::toggled, this,
+			[&](bool checked) { if (checked) {toolButtonAdjustToMarginLeft->setChecked(false);} });
+		connect(toolButtonAdjustToMarginTop, &QToolButton::toggled, this,
+			[&](bool checked) { if (checked) {toolButtonAdjustToMarginBottom->setChecked(false);} });
+		connect(toolButtonAdjustToMarginBottom, &QToolButton::toggled, this,
+			[&](bool checked) { if (checked) {toolButtonAdjustToMarginTop->setChecked(false);} });
+	}
 	radioButtonPageAll->setChecked(true);
 
 	// signals and slots connections
@@ -106,6 +151,18 @@ void MultipleDuplicate::getMultiplyData(ItemMultipleDuplicateData& mdData)
 		mdData.pageSelection = 4;
 	mdData.pageRange = lineEditPageRange->text();
 	mdData.pageLinkText = checkBoxPageLinkText->isChecked();
+	if (mdData.type == 2)
+	{
+		if (toolButtonAdjustToMarginLeft->isChecked())
+			mdData.adjustMarginHorizontal = 1;
+		else if (toolButtonAdjustToMarginRight->isChecked())
+			mdData.adjustMarginHorizontal = 2;
+		if (toolButtonAdjustToMarginTop->isChecked())
+			mdData.adjustMarginVertical = 1;
+		else if (toolButtonAdjustToMarginBottom->isChecked())
+			mdData.adjustMarginHorizontal = 2;
+		mdData.copyCount = spinBoxMaxCopies->value();
+	}
 }
 
 void MultipleDuplicate::selectRangeOfPages()
diff --git a/scribus/ui/multipleduplicate.ui b/scribus/ui/multipleduplicate.ui
index 61d54b178..52a63928c 100644
--- a/scribus/ui/multipleduplicate.ui
+++ b/scribus/ui/multipleduplicate.ui
@@ -10,7 +10,7 @@
     <x>0</x>
     <y>0</y>
     <width>426</width>
-    <height>294</height>
+    <height>329</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -381,8 +381,97 @@
          </item>
         </layout>
        </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <widget class="QLabel" name="labelMaxCopies">
+           <property name="text">
+            <string>Number of copies:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="ScrSpinBox" name="spinBoxMaxCopies">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="specialValueText">
+            <string>Auto</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
        <item>
         <layout class="QVBoxLayout" name="verticalLayout_9">
+         <item>
+          <layout class="QHBoxLayout" name="horizontalLayout_2">
+           <item>
+            <widget class="QLabel" name="labelAdjustToMargin">
+             <property name="text">
+              <string>Adjust to margin:</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="toolButtonAdjustToMarginLeft">
+             <property name="text">
+              <string>...</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="toolButtonAdjustToMarginRight">
+             <property name="text">
+              <string>...</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="toolButtonAdjustToMarginTop">
+             <property name="text">
+              <string>...</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QToolButton" name="toolButtonAdjustToMarginBottom">
+             <property name="text">
+              <string>...</string>
+             </property>
+            </widget>
+           </item>
+           <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>
+          </layout>
+         </item>
          <item>
           <widget class="QCheckBox" name="checkBoxPageLinkText">
            <property name="text">
@@ -423,7 +512,7 @@
   <customwidget>
    <class>ScrSpinBox</class>
    <extends>QDoubleSpinBox</extends>
-   <header location="global">ui/scrspinbox.h</header>
+   <header>ui/scrspinbox.h</header>
   </customwidget>
  </customwidgets>
  <tabstops>
diff --git a/scribus/usertaskstructs.h b/scribus/usertaskstructs.h
index 8c498283e..d6193176c 100644
--- a/scribus/usertaskstructs.h
+++ b/scribus/usertaskstructs.h
@@ -34,7 +34,7 @@ struct InsertAFrameData
 
 struct ItemMultipleDuplicateData
 {
-	int type = 0;
+	int type = 0; // 0 = by number, 1 = by rows & columns, 2 = by page
 	int copyCount = 0;
 	int copyShiftOrGap = 0;
 	double copyShiftGapH = 0.0;
@@ -47,6 +47,8 @@ struct ItemMultipleDuplicateData
 	int pageSelection = 0; // 1 = All, 2 = Even, 3 = Odd, 4 = Range
 	QString pageRange;
 	bool pageLinkText = false;
+	int adjustMarginHorizontal = 0; // 0 = None, 1 = Left / Inside, 2 = Right / Outside
+	int adjustMarginVertical = 0; // 0 = None, 1 = Top, 2 = Bottom
 };
 
 struct CreateRangeData
duplicate-margins.diff (11,299 bytes)   

Issue History

Date Modified Username Field Change
2024-03-14 07:15 ale New Issue
2024-03-14 07:15 ale File Added: duplicate-margin.png
2024-03-14 09:44 ale Note Added: 0051035
2024-03-14 10:22 ale Note Added: 0051036
2024-03-14 10:22 ale File Added: duplicate-copies.png
2024-03-14 10:52 ale Note Added: 0051037
2024-03-14 10:52 ale File Added: duplicate-margins.diff
2024-03-14 16:07 ale Relationship added related to 0017175