1 
2 
3 #include "filmstripselection.h"
4 
5 // Tnz6 includes
6 #include "menubarcommandids.h"
7 #include "filmstripcommand.h"
8 #include "addfilmstripframespopup.h"
9 #include "renumberpopup.h"
10 #include "tapp.h"
11 
12 // TnzTools includes
13 #include "tools/rasterselection.h"
14 #include "tools/strokeselection.h"
15 #include "tools/toolhandle.h"
16 #include "tools/tool.h"
17 
18 // TnzQt includes
19 #include "toonzqt/strokesdata.h"
20 #include "toonzqt/gutil.h"
21 
22 // TnzLib includes
23 #include "toonz/txshlevelhandle.h"
24 #include "toonz/tframehandle.h"
25 #include "toonz/txshlevel.h"
26 #include "toonz/txshsimplelevel.h"
27 #include "toonz/txshleveltypes.h"
28 
29 // TnzCore includes
30 #include "tundo.h"
31 
32 // Qt includes
33 #include <QApplication>
34 #include <QClipboard>
35 
36 //-----------------------------------------------------------------------------
37 
TFilmstripSelection()38 TFilmstripSelection::TFilmstripSelection()
39     : m_inbetweenRange(TFrameId(1), TFrameId(0)) {}
40 
41 //-----------------------------------------------------------------------------
42 
~TFilmstripSelection()43 TFilmstripSelection::~TFilmstripSelection() {}
44 
45 //-----------------------------------------------------------------------------
46 
enableCommands()47 void TFilmstripSelection::enableCommands() {
48   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
49   if (!sl) return;
50 
51   enableCommand(this, MI_SelectAll, &TFilmstripSelection::selectAll);
52   enableCommand(this, MI_InvertSelection,
53                 &TFilmstripSelection::invertSelection);
54 
55   int type       = sl->getType();
56   TFilePath path = sl->getPath();
57 
58   bool doEnable =
59       (type == PLI_XSHLEVEL || type == TZP_XSHLEVEL || type == MESH_XSHLEVEL ||
60        (type == OVL_XSHLEVEL && path.getType() != "psd" &&
61         path.getType() != "gif" && path.getType() != "mp4" &&
62         path.getType() != "webm"));
63 
64   TRasterImageP ri = (TRasterImageP)sl->getSimpleLevel()->getFrame(
65       sl->getSimpleLevel()->getFirstFid(), false);
66 
67   bool isNotEditableFullColorLevel =
68       ((type == OVL_XSHLEVEL && path.getFrame() == TFrameId::NO_FRAME) ||
69        (ri && ri->isScanBW()));
70 
71   if (doEnable && !isNotEditableFullColorLevel) {
72     enableCommand(this, MI_Cut, &TFilmstripSelection::cutFrames);
73     enableCommand(this, MI_Copy, &TFilmstripSelection::copyFrames);
74     enableCommand(this, MI_Paste, &TFilmstripSelection::pasteFrames);
75     enableCommand(this, MI_PasteInto, &TFilmstripSelection::pasteInto);
76     enableCommand(this, MI_Clear, &TFilmstripSelection::deleteFrames);
77     enableCommand(this, MI_Reverse, &TFilmstripSelection::reverseFrames);
78     enableCommand(this, MI_Swing, &TFilmstripSelection::swingFrames);
79     enableCommand(this, MI_Step2, &TFilmstripSelection::stepFrames, 2);
80     enableCommand(this, MI_Step3, &TFilmstripSelection::stepFrames, 3);
81     enableCommand(this, MI_Step4, &TFilmstripSelection::stepFrames, 4);
82     enableCommand(this, MI_Each2, &TFilmstripSelection::eachFrames, 2);
83     enableCommand(this, MI_Each3, &TFilmstripSelection::eachFrames, 3);
84     enableCommand(this, MI_Each4, &TFilmstripSelection::eachFrames, 4);
85     enableCommand(this, MI_Duplicate, &TFilmstripSelection::duplicateFrames);
86 
87     if (type != MESH_XSHLEVEL) {
88       enableCommand(this, MI_Insert, &TFilmstripSelection::insertEmptyFrames);
89       enableCommand(this, MI_MergeFrames, &TFilmstripSelection::mergeFrames);
90 
91       enableCommand(this, MI_AddFrames, &TFilmstripSelection::addFrames);
92     }
93   } else if (isNotEditableFullColorLevel)
94     enableCommand(this, MI_Copy, &TFilmstripSelection::copyFrames);
95 
96   enableCommand(this, MI_ExposeResource, &TFilmstripSelection::exposeFrames);
97 
98   if (doEnable && !isNotEditableFullColorLevel)
99     enableCommand(this, MI_Renumber, &TFilmstripSelection::renumberFrames);
100 }
101 
102 //-----------------------------------------------------------------------------
103 
isEmpty() const104 bool TFilmstripSelection::isEmpty() const { return m_selectedFrames.empty(); }
105 
106 //-----------------------------------------------------------------------------
107 
updateInbetweenRange()108 void TFilmstripSelection::updateInbetweenRange() {
109   // ibrange = (la prima) sequenza di almeno tre frame selezionati consecutivi
110   m_inbetweenRange = std::make_pair(TFrameId(1), TFrameId(0));
111   if (m_selectedFrames.size() < 3)
112     return;  // ci vogliono almeno tre frames selezionati
113   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
114   if (sl) {
115     std::vector<TFrameId> fids;
116     sl->getFids(fids);
117     int m = (int)fids.size();
118     int i, j = -1;
119     for (i = 0; i < (int)fids.size(); i++)
120       if (isSelected(fids[i])) {
121         if (j < 0) j = i;
122       } else {
123         if (j >= 0 && i - j >= 3) break;
124         j = -1;
125       }
126     if (j >= 0 && i - j >= 3) {
127       m_inbetweenRange = std::make_pair(fids[j], fids[i - 1]);
128     }
129   }
130 }
131 
132 //-----------------------------------------------------------------------------
133 
select(const TFrameId & fid,bool selected)134 void TFilmstripSelection::select(const TFrameId &fid, bool selected) {
135   TApp *app = TApp::instance();
136 
137   if (selected)
138     m_selectedFrames.insert(fid);
139   else
140     m_selectedFrames.erase(fid);
141 
142   updateInbetweenRange();
143 
144   TTool *tool = app->getCurrentTool()->getTool();
145   if (tool) tool->setSelectedFrames(m_selectedFrames);
146 
147   TXshSimpleLevel *sl = app->getCurrentLevel()->getSimpleLevel();
148   bool rasterLevel    = sl->getType() == TZP_XSHLEVEL ||
149                      sl->getType() == OVL_XSHLEVEL ||
150                      sl->getType() == TZI_XSHLEVEL;
151 
152   CommandManager::instance()->enable(MI_CanvasSize, rasterLevel);
153 }
154 
155 //-----------------------------------------------------------------------------
156 
isSelected(const TFrameId & fid) const157 bool TFilmstripSelection::isSelected(const TFrameId &fid) const {
158   return m_selectedFrames.count(fid) > 0;
159 }
160 
161 //-----------------------------------------------------------------------------
162 
selectNone()163 void TFilmstripSelection::selectNone() {
164   m_selectedFrames.clear();
165   updateInbetweenRange();
166   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
167   CommandManager::instance()->enable(MI_CanvasSize, false);
168 }
169 
170 //-----------------------------------------------------------------------------
171 
selectAll()172 void TFilmstripSelection::selectAll() {
173   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
174   if (!sl) return;
175   std::vector<TFrameId> fids;
176   sl->getFids(fids);
177   m_selectedFrames.clear();
178   m_selectedFrames.insert(fids.begin(), fids.end());
179   updateInbetweenRange();
180   TTool *tool = TApp::instance()->getCurrentTool()->getTool();
181   tool->setSelectedFrames(m_selectedFrames);
182   bool rasterLevel = sl->getType() == TZP_XSHLEVEL ||
183                      sl->getType() == OVL_XSHLEVEL ||
184                      sl->getType() == TZI_XSHLEVEL;
185   CommandManager::instance()->enable(MI_CanvasSize, rasterLevel);
186   notifyView();
187 }
188 
189 //-----------------------------------------------------------------------------
190 
invertSelection()191 void TFilmstripSelection::invertSelection() {
192   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
193   if (!sl) return;
194   std::vector<TFrameId> fids;
195   sl->getFids(fids);
196   std::set<TFrameId> oldSelectedFrames = m_selectedFrames;
197   m_selectedFrames.clear();
198   std::vector<TFrameId>::iterator it;
199   for (it = fids.begin(); it != fids.end(); it++) {
200     if (oldSelectedFrames.find(*it) != oldSelectedFrames.end()) continue;
201     m_selectedFrames.insert(*it);
202   }
203   updateInbetweenRange();
204   TTool *tool = TApp::instance()->getCurrentTool()->getTool();
205   tool->setSelectedFrames(m_selectedFrames);
206   if (sl->getType() == TZP_XSHLEVEL || sl->getType() == OVL_XSHLEVEL ||
207       sl->getType() == TZI_XSHLEVEL)
208     CommandManager::instance()->enable(MI_CanvasSize, true);
209   notifyView();
210 }
211 
212 //-----------------------------------------------------------------------------
213 
addFrames()214 void TFilmstripSelection::addFrames() {
215   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
216   if (!sl) return;
217   AddFilmstripFramesPopup popup;
218   int ret = popup.exec();
219   if (ret == 0) return;
220 
221   int startFrame = 1;
222   int endFrame   = 1;
223   int stepFrame  = 1;
224 
225   popup.getParameters(startFrame, endFrame, stepFrame);
226   FilmstripCmd::addFrames(sl, startFrame, endFrame, stepFrame);
227 }
228 
229 //-----------------------------------------------------------------------------
230 
copyFrames()231 void TFilmstripSelection::copyFrames() {
232   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
233   if (sl) FilmstripCmd::copy(sl, m_selectedFrames);
234 }
235 
236 //-----------------------------------------------------------------------------
237 
cutFrames()238 void TFilmstripSelection::cutFrames() {
239   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
240   if (sl) {
241     int firstSelectedIndex = sl->fid2index(*m_selectedFrames.begin());
242     assert(firstSelectedIndex >= 0);
243     FilmstripCmd::cut(sl, m_selectedFrames);
244     selectNone();
245     TFrameId fId = (firstSelectedIndex == 0)
246                        ? sl->getFirstFid()
247                        : sl->getFrameId(firstSelectedIndex - 1);
248     TApp::instance()->getCurrentFrame()->setFid(fId);
249     select(fId);
250   }
251 }
252 
253 //-----------------------------------------------------------------------------
254 
pasteFrames()255 void TFilmstripSelection::pasteFrames() {
256   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
257   if (!sl) return;
258 
259   std::set<TFrameId> fids;
260   if (m_selectedFrames.empty()) {
261     if (sl->isSubsequence()) return;
262     fids.insert(TApp::instance()->getCurrentFrame()->getFid());
263   } else
264     fids = m_selectedFrames;
265 
266   FilmstripCmd::paste(sl, fids);
267 }
268 
269 //-----------------------------------------------------------------------------
270 
mergeFrames()271 void TFilmstripSelection::mergeFrames() {
272   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
273   if (sl) FilmstripCmd::merge(sl, m_selectedFrames);
274 }
275 
276 //-----------------------------------------------------------------------------
277 
pasteInto()278 void TFilmstripSelection::pasteInto() {
279   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
280   if (sl) FilmstripCmd::pasteInto(sl, m_selectedFrames);
281 }
282 
283 //-----------------------------------------------------------------------------
284 
deleteFrames()285 void TFilmstripSelection::deleteFrames() {
286   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
287   if (sl) FilmstripCmd::clear(sl, m_selectedFrames);
288   updateInbetweenRange();
289 }
290 
291 //-----------------------------------------------------------------------------
292 
insertEmptyFrames()293 void TFilmstripSelection::insertEmptyFrames() {
294   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
295   if (sl) FilmstripCmd::insert(sl, m_selectedFrames, true);
296 }
297 
298 //-----------------------------------------------------------------------------
299 
reverseFrames()300 void TFilmstripSelection::reverseFrames() {
301   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
302   if (sl) FilmstripCmd::reverse(sl, m_selectedFrames);
303 }
304 
305 //-----------------------------------------------------------------------------
306 
swingFrames()307 void TFilmstripSelection::swingFrames() {
308   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
309   if (sl) FilmstripCmd::swing(sl, m_selectedFrames);
310 }
311 
312 //-----------------------------------------------------------------------------
313 
stepFrames(int step)314 void TFilmstripSelection::stepFrames(int step) {
315   if (step < 2) return;
316   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
317   if (sl) FilmstripCmd::step(sl, m_selectedFrames, step);
318   updateInbetweenRange();
319 }
320 
321 //-----------------------------------------------------------------------------
322 
eachFrames(int each)323 void TFilmstripSelection::eachFrames(int each) {
324   if (each < 2) return;
325   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
326   if (sl) FilmstripCmd::each(sl, m_selectedFrames, each);
327   updateInbetweenRange();
328 }
329 
330 //-----------------------------------------------------------------------------
331 
duplicateFrames()332 void TFilmstripSelection::duplicateFrames() {
333   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
334   if (sl) FilmstripCmd::duplicate(sl, m_selectedFrames, true);
335 }
336 
337 //-----------------------------------------------------------------------------
338 
exposeFrames()339 void TFilmstripSelection::exposeFrames() {
340   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
341   if (sl) FilmstripCmd::moveToScene(sl, m_selectedFrames);
342 }
343 
344 //-----------------------------------------------------------------------------
345 
renumberFrames()346 void TFilmstripSelection::renumberFrames() {
347   TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel();
348   if (!sl) return;
349   if (m_selectedFrames.empty()) return;
350   TFrameId fid = *m_selectedFrames.begin();
351   RenumberPopup popup;
352   popup.setValues(fid.getNumber(), 1);
353   int ret = popup.exec();
354   if (ret != QDialog::Accepted) return;
355   int startFrame = 0, stepFrame = 0;
356   popup.getValues(startFrame, stepFrame);
357   if (startFrame < 1 || stepFrame < 1) {
358     DVGui::error(("Bad renumber values"));
359     return;
360   }
361   FilmstripCmd::renumber(sl, m_selectedFrames, startFrame, stepFrame);
362   updateInbetweenRange();
363 }
364