1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 *   Copyright (C) 2007 by Franz Schmid                                     *
9 *   franz.schmid@altmuehlnet.de                                            *
10 *                                                                          *
11 *   This program is free software; you can redistribute it and/or modify   *
12 *   it under the terms of the GNU General Public License as published by   *
13 *   the Free Software Foundation; either version 2 of the License, or      *
14 *   (at your option) any later version.                                    *
15 *                                                                          *
16 *   This program is distributed in the hope that it will be useful,        *
17 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
18 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
19 *   GNU General Public License for more details.                           *
20 *                                                                          *
21 *   You should have received a copy of the GNU General Public License      *
22 *   along with this program; if not, write to the                          *
23 *   Free Software Foundation, Inc.,                                        *
24 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.              *
25 ****************************************************************************/
26 
27 #include "pathcut.h"
28 #include "scribuscore.h"
29 #include "scribusdoc.h"
30 #include "appmodes.h"
31 #include "selection.h"
32 #include "ui/scmessagebox.h"
33 #include "util.h"
34 #include "iconmanager.h"
35 #include <QPainterPathStroker>
36 #include <QMessageBox>
37 
pathcut_getPluginAPIVersion()38 int pathcut_getPluginAPIVersion()
39 {
40 	return PLUGIN_API_VERSION;
41 }
42 
pathcut_getPlugin()43 ScPlugin* pathcut_getPlugin()
44 {
45 	PathCutPlugin* plug = new PathCutPlugin();
46 	Q_CHECK_PTR(plug);
47 	return plug;
48 }
49 
pathcut_freePlugin(ScPlugin * plugin)50 void pathcut_freePlugin(ScPlugin* plugin)
51 {
52 	PathCutPlugin* plug = qobject_cast<PathCutPlugin*>(plugin);
53 	Q_ASSERT(plug);
54 	delete plug;
55 }
56 
PathCutPlugin()57 PathCutPlugin::PathCutPlugin()
58 {
59 	// Set action info in languageChange, so we only have to do
60 	// it in one place.
61 	languageChange();
62 }
63 
~PathCutPlugin()64 PathCutPlugin::~PathCutPlugin() {};
65 
languageChange()66 void PathCutPlugin::languageChange()
67 {
68 	// Note that we leave the unused members unset. They'll be initialised
69 	// with their default ctors during construction.
70 	// Action name
71 	m_actionInfo.name = "PathCutter";
72 	// Action text for menu, including accel
73 	m_actionInfo.text = tr("Cut Polygon");
74 	m_actionInfo.helpText = tr("Cuts a Polygon with a Path.");
75 	// Menu
76 	m_actionInfo.iconPath1 = "22/transform-crop-and-resize.png";
77 	m_actionInfo.iconPath2 = "22/transform-crop-and-resize.png";
78 	m_actionInfo.menu = "ItemPathOps";
79 	m_actionInfo.parentMenu = "Item";
80 	m_actionInfo.subMenuName = tr("Path Tools");
81 	m_actionInfo.enabledOnStartup = false;
82 	m_actionInfo.notSuitableFor.append(PageItem::Line);
83 	m_actionInfo.notSuitableFor.append(PageItem::TextFrame);
84 	m_actionInfo.notSuitableFor.append(PageItem::ImageFrame);
85 	m_actionInfo.notSuitableFor.append(PageItem::PathText);
86 	m_actionInfo.notSuitableFor.append(PageItem::LatexFrame);
87 	m_actionInfo.notSuitableFor.append(PageItem::Symbol);
88 	m_actionInfo.notSuitableFor.append(PageItem::RegularPolygon);
89 	m_actionInfo.notSuitableFor.append(PageItem::Arc);
90 	m_actionInfo.notSuitableFor.append(PageItem::Spiral);
91 	m_actionInfo.forAppMode.append(modeNormal);
92 	m_actionInfo.needsNumObjects = 2;
93 	m_actionInfo.firstObjectType.append(PageItem::PolyLine);
94 	m_actionInfo.secondObjectType.append(PageItem::Polygon);
95 }
96 
fullTrName() const97 QString PathCutPlugin::fullTrName() const
98 {
99 	return QObject::tr("PathCutter");
100 }
101 
getAboutData() const102 const ScActionPlugin::AboutData* PathCutPlugin::getAboutData() const
103 {
104 	AboutData* about = new AboutData;
105 	Q_CHECK_PTR(about);
106 	about->authors = QString::fromUtf8("Franz Schmid <Franz.Schmid@altmuehlnet.de>");
107 	about->shortDescription = tr("Cuts a Polygon by a Polyline");
108 	about->description = tr("Cuts a Polygon by a Polyline");
109 	// about->version
110 	// about->releaseDate
111 	// about->copyright
112 	about->license = "GPL";
113 	return about;
114 }
115 
deleteAboutData(const AboutData * about) const116 void PathCutPlugin::deleteAboutData(const AboutData* about) const
117 {
118 	Q_ASSERT(about);
119 	delete about;
120 }
121 
run(ScribusDoc * doc,const QString &)122 bool PathCutPlugin::run(ScribusDoc* doc, const QString&)
123 {
124 	ScribusDoc* currDoc = doc;
125 	if (currDoc == nullptr)
126 		currDoc = ScCore->primaryMainWindow()->doc;
127 	if (currDoc->m_Selection->count() > 1)
128 	{
129 		PageItem *Item1 = currDoc->m_Selection->itemAt(0);
130 		PageItem *Item2 = currDoc->m_Selection->itemAt(1);
131 		if (Item1->itemType() != PageItem::PolyLine)
132 		{
133 			Item1 = currDoc->m_Selection->itemAt(1);
134 			Item2 = currDoc->m_Selection->itemAt(0);
135 		}
136 		FPointArray path = Item1->PoLine;
137 		QPainterPathStroker stroke;
138 		stroke.setWidth(Item1->lineWidth());
139 		QPainterPath cutter = stroke.createStroke(path.toQPainterPath(false));
140 		QTransform ms;
141 		ms.translate(Item1->xPos() - Item2->xPos(), Item1->yPos() - Item2->yPos());
142 		ms.rotate(Item1->rotation());
143 		cutter = ms.map(cutter);
144 		path.map(ms);
145 		FPoint start = path.point(0);
146 		FPoint end = path.point(path.size()-2);
147 		QTransform mm;
148 		mm.rotate(Item2->rotation());
149 		QPainterPath objekt = mm.map(Item2->PoLine.toQPainterPath(true));
150 		if ((objekt.contains(QPointF(start.x(), start.y()))) || (objekt.contains(QPointF(end.x(), end.y()))))
151 		{
152 			ScMessageBox::information(doc->scMW(), tr("Error"), tr("The cutting line must cross the polygon and\nboth end points must lie outside of the polygon"));
153 			return true;
154 		}
155 		QPainterPath result = objekt.subtracted(cutter);
156 		FPointArray points;
157 		points.fromQPainterPath(result);
158 		Item2->PoLine = points;
159 		Item2->ClipEdited = true;
160 		Item2->FrameType = 3;
161 		currDoc->adjustItemSize(Item2);
162 		Item2->OldB2 = Item2->width();
163 		Item2->OldH2 = Item2->height();
164 		Item2->updateClip();
165 		Item2->ContourLine = Item2->PoLine.copy();
166 //		currDoc->m_Selection->clear();
167 //		currDoc->m_Selection->addItem(Item1);
168 //		currDoc->itemSelection_DeleteItem();
169 		currDoc->m_Selection->clear();
170 		currDoc->m_Selection->addItem(Item2);
171 		currDoc->itemSelection_SplitItems();
172 		currDoc->changed();
173 	}
174 	return true;
175 }
176