1 
2 
3 #include "duplicatepopup.h"
4 
5 // Tnz6 includes
6 #include "filmstripcommand.h"
7 #include "cellselection.h"
8 #include "tapp.h"
9 
10 // TnzQt includes
11 #include "toonzqt/tselectionhandle.h"
12 
13 #include "menubarcommandids.h"
14 #include "tundo.h"
15 #include "toonz/tscenehandle.h"
16 #include "toonz/txsheethandle.h"
17 #include "toonz/toonzscene.h"
18 #include "historytypes.h"
19 
20 // Qt includes
21 #include <QPushButton>
22 #include <QLabel>
23 #include <QMainWindow>
24 
25 //=============================================================================
26 // Duplicate
27 //-----------------------------------------------------------------------------
28 
29 //-----------------------------------------------------------------------------
30 namespace {
31 //-----------------------------------------------------------------------------
32 
33 class DuplicateUndo final : public TUndo {
34   int m_r0, m_c0;
35   int m_r1, m_c1;
36   int m_upTo;
37 
38 public:
39   DuplicateUndo(int r0, int c0, int r1, int c1, int upTo);
~DuplicateUndo()40   ~DuplicateUndo() {}
41   void undo() const override;
42   void redo() const override;
43   void repeat() const;
44 
getSize() const45   int getSize() const override { return sizeof(*this); }
46 
getHistoryString()47   QString getHistoryString() override { return QObject::tr("Duplicate"); }
48 
getHistoryType()49   int getHistoryType() override { return HistoryType::Xsheet; }
50 };
51 
52 //-----------------------------------------------------------------------------
53 
DuplicateUndo(int r0,int c0,int r1,int c1,int upTo)54 DuplicateUndo::DuplicateUndo(int r0, int c0, int r1, int c1, int upTo)
55     : m_r0(r0), m_c0(c0), m_r1(r1), m_c1(c1), m_upTo(upTo) {}
56 
57 //-----------------------------------------------------------------------------
58 
undo() const59 void DuplicateUndo::undo() const {
60   if (m_r0 == 0 && m_c0 == 0 && m_r1 == -1 && m_c1 == -1) return;
61   TApp *app = TApp::instance();
62   for (int j = m_c0; j <= m_c1; j++)
63     app->getCurrentXsheet()->getXsheet()->removeCells(m_r1 + 1, j,
64                                                       m_upTo - (m_r1 + 1) + 1);
65   app->getCurrentXsheet()->notifyXsheetChanged();
66 }
67 
68 //-----------------------------------------------------------------------------
69 
redo() const70 void DuplicateUndo::redo() const {
71   if (m_r0 == 0 && m_c0 == 0 && m_r1 == -1 && m_c1 == -1) return;
72   TApp *app = TApp::instance();
73   app->getCurrentXsheet()->getXsheet()->duplicateCells(m_r0, m_c0, m_r1, m_c1,
74                                                        m_upTo);
75   app->getCurrentXsheet()->notifyXsheetChanged();
76 }
77 
78 //-----------------------------------------------------------------------------
79 
repeat() const80 void DuplicateUndo::repeat() const {}
81 
82 //-----------------------------------------------------------------------------
83 }  // namespace
84 //-----------------------------------------------------------------------------
85 
86 //=============================================================================
87 // DuplicatePopup
88 //-----------------------------------------------------------------------------
89 /*--  "Repeat..." というコマンド  --*/
DuplicatePopup()90 DuplicatePopup::DuplicatePopup()
91     : QDialog(TApp::instance()->getMainWindow()), m_count(0), m_upTo(0) {
92   setWindowTitle(tr("Repeat"));
93 
94   m_countFld = new DVGui::IntLineEdit(this);
95   m_upToFld  = new DVGui::IntLineEdit(this);
96 
97   m_okBtn     = new QPushButton(tr("Repeat"), this);
98   m_cancelBtn = new QPushButton(tr("Close"), this);
99   m_applyBtn  = new QPushButton(tr("Apply"), this);
100 
101   //----layout
102   QVBoxLayout *mainLayout = new QVBoxLayout();
103   mainLayout->setMargin(10);
104   mainLayout->setSpacing(10);
105   {
106     QHBoxLayout *upperLay = new QHBoxLayout();
107     upperLay->setMargin(0);
108     upperLay->setSpacing(5);
109     {
110       upperLay->addWidget(new QLabel(tr("Times:"), this), 0);
111       upperLay->addWidget(m_countFld, 1);
112       upperLay->addSpacing(10);
113       upperLay->addWidget(new QLabel(tr("Up to Frame:"), this), 0);
114       upperLay->addWidget(m_upToFld, 1);
115     }
116     mainLayout->addLayout(upperLay, 0);
117 
118     QHBoxLayout *bottomLay = new QHBoxLayout();
119     bottomLay->setMargin(0);
120     bottomLay->setSpacing(10);
121     {
122       bottomLay->addWidget(m_okBtn);
123       bottomLay->addWidget(m_applyBtn);
124       bottomLay->addWidget(m_cancelBtn);
125     }
126     mainLayout->addLayout(bottomLay, 0);
127   }
128   setLayout(mainLayout);
129 
130   //----signal-slot connections
131   bool ret = true;
132   ret      = ret && connect(m_countFld, SIGNAL(editingFinished()), this,
133                        SLOT(updateValues()));
134   ret = ret && connect(m_upToFld, SIGNAL(editingFinished()), this,
135                        SLOT(updateValues()));
136 
137   ret = ret && connect(m_okBtn, SIGNAL(clicked()), this, SLOT(onOKPressed()));
138   ret = ret && connect(m_cancelBtn, SIGNAL(clicked()), this, SLOT(close()));
139   ret = ret &&
140         connect(m_applyBtn, SIGNAL(clicked()), this, SLOT(onApplyPressed()));
141 
142   ret = ret && connect(TApp::instance()->getCurrentSelection(),
143                        SIGNAL(selectionChanged(TSelection *)), this,
144                        SLOT(onSelectionChanged()));
145   assert(ret);
146 }
147 
148 //-------------------------------------------------------------------
149 
onApplyPressed()150 void DuplicatePopup::onApplyPressed() {
151   TCellSelection *selection = dynamic_cast<TCellSelection *>(
152       TApp::instance()->getCurrentSelection()->getSelection());
153   if (!selection) return;
154 
155   int count = 0, upTo = 0;
156   getValues(count, upTo);
157 
158   try {
159     int r0, r1, c0, c1;
160     selection->getSelectedCells(r0, c0, r1, c1);
161     TUndo *undo = new DuplicateUndo(r0, c0, r1, c1, (int)upTo - 1);
162     TUndoManager::manager()->add(undo);
163     TApp *app         = TApp::instance();
164     ToonzScene *scene = app->getCurrentScene()->getScene();
165     TXsheet *xsh      = scene->getXsheet();
166     xsh->duplicateCells(r0, c0, r1, c1, (int)upTo - 1);
167     TApp::instance()->getCurrentScene()->setDirtyFlag(true);
168     TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
169   } catch (...) {
170     DVGui::error(("Cannot duplicate"));
171   }
172 }
173 
174 //-------------------------------------------------------------------
175 
onOKPressed()176 void DuplicatePopup::onOKPressed() {
177   onApplyPressed();
178   close();
179 }
180 
181 //-------------------------------------------------------------------
182 
onSelectionChanged()183 void DuplicatePopup::onSelectionChanged() {
184   if (isVisible()) {
185     m_count = 0;
186     updateValues();
187   }
188 }
189 
190 //-------------------------------------------------------------------
191 
showEvent(QShowEvent *)192 void DuplicatePopup::showEvent(QShowEvent *) {
193   /*-- ダイアログを開くたびにcount値を初期値に戻す --*/
194   m_countFld->setValue(1);
195   m_upToFld->setValue(1);
196   m_count = 0;
197   m_upTo  = 0;
198   updateValues();
199 }
200 
201 //-------------------------------------------------------------------
202 
updateValues()203 void DuplicatePopup::updateValues() {
204   int count, upTo;
205   getValues(count, upTo);
206   if (count == m_count && upTo == m_upTo) return;
207   TCellSelection *selection = dynamic_cast<TCellSelection *>(
208       TApp::instance()->getCurrentSelection()->getSelection());
209 
210   if (!selection) {
211     m_countFld->setEnabled(false);
212     m_upToFld->setEnabled(false);
213     m_okBtn->setEnabled(false);
214     m_applyBtn->setEnabled(false);
215     return;
216   } else {
217     m_countFld->setEnabled(true);
218     m_upToFld->setEnabled(true);
219     m_okBtn->setEnabled(true);
220     m_applyBtn->setEnabled(true);
221   }
222 
223   int r0, r1, c0, c1;
224   selection->getSelectedCells(r0, c0, r1, c1);
225   int chunkSize = r1 - r0 + 1;
226 
227   if (count != m_count) {
228     if (count < 1) count = 1;
229     upTo                 = r1 + 1 + count * chunkSize;
230   }
231   /*-- upToを編集した場合 --*/
232   else {
233     if (upTo < r1 + 1 + 1) upTo = r1 + 1 + 1;
234     count                       = (upTo - (r1 + 2) + chunkSize) / chunkSize;
235     if (count < 1) upTo         = 1;
236   }
237   m_count = count;
238   m_upTo  = upTo;
239 
240   m_countFld->setText(QString::number(m_count));
241   m_upToFld->setText(QString::number(m_upTo));
242 }
243 
244 //-------------------------------------------------------------------
245 
getValues(int & count,int & upTo)246 void DuplicatePopup::getValues(int &count, int &upTo) {
247   count = m_countFld->text().toInt();
248   upTo  = m_upToFld->text().toInt();
249 }
250 
251 OpenPopupCommandHandler<DuplicatePopup> openDuplicatePopup(MI_Dup);
252