#include "toonzqt/stylenameeditor.h" // TnzQt includes #include "toonzqt/gutil.h" // TnzLib includes #include "toonz/toonzfolders.h" #include "toonz/palettecmd.h" #include "toonz/tpalettehandle.h" // TnzCore includes #include "tsystem.h" #include "tcommon.h" #include "tcolorstyles.h" #include "tpalette.h" #include #include #include #include #include #include #include #include #include #include #include #include //------------------------------------------------------------ namespace { const int areaColCount[WORD_COLUMN_AMOUNT] = {2, 2, 1}; const QString columnLabel[WORD_COLUMN_AMOUNT] = {AddWordButton::tr("Character"), AddWordButton::tr("Part"), AddWordButton::tr("Suffix")}; int indexToRow(int index, int columnId) { return index / areaColCount[columnId]; } int indexToCol(int index, int columnId) { return index % areaColCount[columnId]; } }; // namespace //------------------------------------------------------------ NewWordDialog::NewWordDialog(QWidget* parent) { setModal(true); m_lineEdit = new QLineEdit(this); QPushButton* okBtn = new QPushButton(tr("OK"), this); QPushButton* cancelBtn = new QPushButton(tr("Cancel"), this); // layout QVBoxLayout* mainLay = new QVBoxLayout(); mainLay->setMargin(5); mainLay->setSpacing(5); { mainLay->addWidget(new QLabel(tr("Enter new word"), this), 0, Qt::AlignLeft | Qt::AlignVCenter); mainLay->addWidget(m_lineEdit, 0); QHBoxLayout* buttonsLay = new QHBoxLayout(); buttonsLay->setMargin(3); buttonsLay->setSpacing(20); { buttonsLay->addSpacing(1); buttonsLay->addWidget(okBtn, 0); buttonsLay->addWidget(cancelBtn, 0); buttonsLay->addSpacing(1); } mainLay->addLayout(buttonsLay); } setLayout(mainLay); // signal-slot connections bool ret = true; ret = ret && connect(okBtn, SIGNAL(clicked(bool)), this, SLOT(accept())); ret = ret && connect(cancelBtn, SIGNAL(clicked(bool)), this, SLOT(reject())); } //------- QString NewWordDialog::getName() { return m_lineEdit->text(); } //------------------------------------------------------------ WordButton::WordButton(const QString& text, QWidget* parent) : QPushButton(text, parent) { setFixedHeight(23); setMinimumWidth(75); setObjectName("WordButton"); setToolTip(text); bool ret = connect(this, SIGNAL(clicked(bool)), this, SLOT(onClicked())); assert(ret); } //------- void WordButton::onClicked() { emit clicked(text()); } //------- void WordButton::onRemove() { emit removeWord(text()); } //------- void WordButton::contextMenuEvent(QContextMenuEvent* event) { QMenu menu(this); QAction* removeAct = new QAction(tr("Remove %1").arg(text()), &menu); bool ret = connect(removeAct, SIGNAL(triggered()), this, SLOT(onRemove())); menu.addAction(removeAct); menu.exec(event->globalPos()); } //------------------------------------------------------------ AddWordButton::AddWordButton(const int col, QWidget* parent) : WordButton(tr("New"), parent), m_column(col) { // setFixedSize(23, 23); setIcon(QIcon(":Resources/plus.svg")); setIconSize(QSize(16, 16)); setToolTip(tr("Add New Word for %1").arg(columnLabel[col])); } //------- void AddWordButton::onClicked() { emit clicked(m_column); } //------------------------------------------------------------ //------- // load word list from user's settings void EasyInputArea::loadList() { TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath(styleNameEasyInputWordsFileName)); if (!TFileStatus(fp).doesExist()) return; QSettings wordsSettings(toQString(fp), QSettings::IniFormat); for (int a = 0; a < WORD_COLUMN_AMOUNT; a++) { int size = wordsSettings.beginReadArray(QString::number(a)); if (size == 0) continue; for (int i = 0; i < size; ++i) { wordsSettings.setArrayIndex(i); m_wordList[a].append(wordsSettings.value("word").toString()); } wordsSettings.endArray(); } } //------- // save word list to user's settings void EasyInputArea::saveList() { TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath(styleNameEasyInputWordsFileName)); QSettings wordsSettings(toQString(fp), QSettings::IniFormat); wordsSettings.clear(); for (int a = 0; a < WORD_COLUMN_AMOUNT; a++) { wordsSettings.beginWriteArray(QString::number(a)); for (int i = 0; i < m_wordList[a].count(); ++i) { wordsSettings.setArrayIndex(i); wordsSettings.setValue("word", m_wordList[a].at(i)); } wordsSettings.endArray(); } } //------ void EasyInputArea::updatePanelSize(int columnId) { int itemCount = m_wordList[columnId].size() + 1; int rowCount = tceil((double)itemCount / (double)areaColCount[columnId]); QWidget* widget = m_scrollArea[columnId]->widget(); widget->setFixedSize(m_scrollArea[columnId]->width(), rowCount * 26 + 3); } //------ EasyInputArea::EasyInputArea(QWidget* parent) : QWidget(parent) { loadList(); QHBoxLayout* mainLay = new QHBoxLayout(); mainLay->setMargin(0); mainLay->setSpacing(3); for (int a = 0; a < WORD_COLUMN_AMOUNT; a++) { m_scrollArea[a] = new QScrollArea(this); m_scrollArea[a]->setObjectName("SolidLineFrame"); QFrame* wordPanel = new QFrame(this); QGridLayout* buttonsLay = new QGridLayout(); buttonsLay->setMargin(3); buttonsLay->setSpacing(3); { int row = 0; int col = 0; // store word buttons for (int s = 0; s < m_wordList[a].size(); s++) { WordButton* button = new WordButton(m_wordList[a].at(s), this); button->setFocusPolicy(Qt::NoFocus); buttonsLay->addWidget(button, row, col); connect(button, SIGNAL(clicked(const QString&)), this, SIGNAL(wordClicked(const QString&))); connect(button, SIGNAL(removeWord(const QString&)), this, SLOT(onRemoveWord(const QString&))); col++; if (col == areaColCount[a]) { col = 0; row++; } } // add button AddWordButton* addWordButton = new AddWordButton(a, this); addWordButton->setFocusPolicy(Qt::NoFocus); buttonsLay->addWidget(addWordButton, row, col); connect(addWordButton, SIGNAL(clicked(const int)), this, SLOT(addWordButtonClicked(const int))); } for (int c = 0; c < areaColCount[a]; c++) buttonsLay->setColumnStretch(c, 1); wordPanel->setLayout(buttonsLay); m_wordLayout[a] = buttonsLay; m_scrollArea[a]->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_scrollArea[a]->setMinimumWidth(areaColCount[a] * 78 + 3); m_scrollArea[a]->setWidget(wordPanel); mainLay->addWidget(m_scrollArea[a], areaColCount[a]); } setLayout(mainLay); } //------- void EasyInputArea::addWordButtonClicked(const int columnId) { NewWordDialog dialog(this); if (dialog.exec() == QDialog::Rejected) return; QString word = dialog.getName(); if (word.isEmpty()) return; bool found = false; for (int i = 0; i < WORD_COLUMN_AMOUNT; i++) { found = m_wordList[i].contains(word); if (found) break; } if (found) { QMessageBox::warning(this, tr("Warning"), tr("%1 is already registered").arg(word)); return; } // Append word to the list m_wordList[columnId].append(word); // Append new WordButton WordButton* button = new WordButton(word, this); connect(button, SIGNAL(clicked(const QString&)), this, SIGNAL(wordClicked(const QString&))); connect(button, SIGNAL(removeWord(const QString&)), this, SLOT(onRemoveWord(const QString&))); button->setFocusPolicy(Qt::NoFocus); int wordCount = m_wordList[columnId].count(); int row = indexToRow(wordCount - 1, columnId); int col = indexToCol(wordCount - 1, columnId); QWidget* addBtn = m_wordLayout[columnId]->itemAtPosition(row, col)->widget(); m_wordLayout[columnId]->addWidget(button, row, col); // Move add button to the next index col++; if (col == areaColCount[columnId]) { col = 0; row++; } m_wordLayout[columnId]->addWidget(addBtn, row, col); updatePanelSize(columnId); saveList(); } //------------------------------------------------------------ void EasyInputArea::onRemoveWord(const QString& word) { int a = -1; int index; for (int i = 0; i < WORD_COLUMN_AMOUNT; i++) { index = m_wordList[i].indexOf(word); if (index >= 0) { a = i; break; } } if (a < 0 || a >= WORD_COLUMN_AMOUNT) return; // delete button int row = indexToRow(index, a); int col = indexToCol(index, a); WordButton* wordButton = qobject_cast( m_wordLayout[a]->itemAtPosition(row, col)->widget()); if (!wordButton) return; bool ret = true; ret = ret && disconnect(wordButton, SIGNAL(clicked(const QString&)), this, SIGNAL(wordClicked(const QString&))); ret = ret && disconnect(wordButton, SIGNAL(removeWord(const QString&)), this, SLOT(onRemoveWord(const QString&))); assert(ret); m_wordLayout[a]->removeWidget(wordButton); wordButton->deleteLater(); // move the following buttons for (int i = index + 1; i <= m_wordList[a].count(); i++) { int row = indexToRow(i, a); int col = indexToCol(i, a); QWidget* button = m_wordLayout[a]->itemAtPosition(row, col)->widget(); col--; if (col < 0) { row--; col = areaColCount[a] - 1; } m_wordLayout[a]->addWidget(button, row, col); } // remove word from the list m_wordList[a].removeAt(index); updatePanelSize(a); } //------------------------------------------------------------ void EasyInputArea::enterEvent(QEvent*) { emit mouseEnter(); } //------------------------------------------------------------ void EasyInputArea::resizeEvent(QResizeEvent*) { for (int i = 0; i < WORD_COLUMN_AMOUNT; i++) { updatePanelSize(i); } } //------------------------------------------------------------ StyleNameEditor::StyleNameEditor(QWidget* parent) : Dialog(parent, false, false, "StyleNameEditor") , m_paletteHandle(0) , m_selectionStart(-1) , m_selectionLength(0) { setWindowTitle(tr("Name Editor")); m_styleName = new QLineEdit(this); m_okButton = new QPushButton(tr("OK"), this); m_cancelButton = new QPushButton(tr("Cancel"), this); m_applyButton = new QPushButton(tr("Apply and Next"), this); EasyInputArea* easyInputArea = new EasyInputArea(this); QLabel* panelLabel[WORD_COLUMN_AMOUNT]; for (int i = 0; i < WORD_COLUMN_AMOUNT; i++) { panelLabel[i] = new QLabel(columnLabel[i], this); panelLabel[i]->setStyleSheet("font-size: 10px; font: italic;"); } setFocusProxy(m_styleName); m_styleName->setEnabled(false); m_okButton->setEnabled(false); m_okButton->setFocusPolicy(Qt::NoFocus); m_applyButton->setEnabled(false); m_applyButton->setFocusPolicy(Qt::NoFocus); m_cancelButton->setFocusPolicy(Qt::NoFocus); m_styleName->setObjectName("LargeSizedText"); easyInputArea->setFocusPolicy(Qt::NoFocus); // QVBoxLayout* mainLayout = new QVBoxLayout(); m_topLayout->setMargin(10); m_topLayout->setSpacing(5); { QHBoxLayout* inputLayout = new QHBoxLayout(); inputLayout->setMargin(0); inputLayout->setSpacing(3); { inputLayout->addWidget(new QLabel(tr("Style Name"), this), 0); inputLayout->addWidget(m_styleName, 1); } m_topLayout->addLayout(inputLayout, 0); QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->setMargin(0); buttonLayout->setSpacing(3); { buttonLayout->addWidget(m_okButton); buttonLayout->addWidget(m_applyButton); buttonLayout->addWidget(m_cancelButton); } m_topLayout->addLayout(buttonLayout, 0); m_topLayout->addSpacing(5); QHBoxLayout* labelLay = new QHBoxLayout(); labelLay->setMargin(0); labelLay->setSpacing(3); { labelLay->addWidget(new QLabel(tr("Easy Inputs"), this), 1, Qt::AlignLeft); for (int i = 0; i < WORD_COLUMN_AMOUNT; i++) { labelLay->addWidget(panelLabel[i], (i == 0) ? areaColCount[i] - 1 : areaColCount[i], Qt::AlignRight | Qt::AlignBottom); } } m_topLayout->addLayout(labelLay, 0); m_topLayout->addWidget(easyInputArea, 1); } bool ret = true; ret = ret && connect(m_okButton, SIGNAL(pressed()), this, SLOT(onOkPressed())); ret = ret && connect(m_cancelButton, SIGNAL(pressed()), this, SLOT(onCancelPressed())); ret = ret && connect(m_applyButton, SIGNAL(pressed()), this, SLOT(onApplyPressed())); ret = ret && connect(easyInputArea, SIGNAL(wordClicked(const QString&)), this, SLOT(onWordClicked(const QString&))); ret = ret && connect(easyInputArea, SIGNAL(mouseEnter()), this, SLOT(storeSelectionInfo())); assert(ret); } //------- void StyleNameEditor::setPaletteHandle(TPaletteHandle* ph) { m_paletteHandle = ph; connect(m_paletteHandle, SIGNAL(colorStyleSwitched()), this, SLOT(onStyleSwitched())); connect(m_paletteHandle, SIGNAL(paletteSwitched()), this, SLOT(onStyleSwitched())); m_styleName->setEnabled(true); m_okButton->setEnabled(true); m_applyButton->setEnabled(true); } //------- void StyleNameEditor::showEvent(QShowEvent* e) { if (m_paletteHandle) { disconnect(m_paletteHandle, SIGNAL(colorStyleSwitched()), this, SLOT(onStyleSwitched())); disconnect(m_paletteHandle, SIGNAL(paletteSwitched()), this, SLOT(onStyleSwitched())); connect(m_paletteHandle, SIGNAL(colorStyleSwitched()), this, SLOT(onStyleSwitched())); connect(m_paletteHandle, SIGNAL(paletteSwitched()), this, SLOT(onStyleSwitched())); } // update view onStyleSwitched(); } //-------disconnection void StyleNameEditor::hideEvent(QHideEvent* e) { disconnect(m_paletteHandle, SIGNAL(colorStyleSwitched()), this, SLOT(onStyleSwitched())); disconnect(m_paletteHandle, SIGNAL(paletteSwitched()), this, SLOT(onStyleSwitched())); } //-----update display when the current style is switched void StyleNameEditor::onStyleSwitched() { if (!m_paletteHandle || !m_paletteHandle->getStyle()) return; std::wstring styleName = m_paletteHandle->getStyle()->getName(); m_styleName->setText(QString::fromStdWString(styleName)); m_styleName->selectAll(); m_styleName->setFocus(); int styleId = m_paletteHandle->getStyleIndex(); setWindowTitle(tr("Name Editor: # %1").arg(styleId)); } //------- void StyleNameEditor::onOkPressed() { onApplyPressed(); close(); } //------- void StyleNameEditor::onApplyPressed() { if (!m_paletteHandle || !m_paletteHandle->getStyle()) return; if (m_styleName->text() == "") return; std::wstring newName = m_styleName->text().toStdWString(); PaletteCmd::renamePaletteStyle(m_paletteHandle, newName); // move the current style to the next TPalette* palette = m_paletteHandle->getPalette(); int currentIndex = m_paletteHandle->getStyleIndex(); TPalette::Page* page = palette->getStylePage(currentIndex); int indexInPage = page->search(currentIndex); // If indexInPage is at the end of the page, then move to the top of the next // page if (indexInPage == page->getStyleCount() - 1) { int pageIndex = page->getIndex(); // if the current page is the last one, then move to the first page while (1) { pageIndex++; if (pageIndex == palette->getPageCount()) pageIndex = 0; page = palette->getPage(pageIndex); if (page->getStyleCount() > 0) break; } currentIndex = page->getStyleId(0); } else currentIndex = page->getStyleId(indexInPage + 1); // change the current index m_paletteHandle->setStyleIndex(currentIndex); } //------- void StyleNameEditor::onCancelPressed() { close(); } //------- // focus when the mouse enters void StyleNameEditor::enterEvent(QEvent* e) { activateWindow(); m_styleName->setFocus(); } //------- void StyleNameEditor::onWordClicked(const QString& word) { if (m_selectionLength != 0) m_styleName->setSelection(m_selectionStart, m_selectionLength); else m_styleName->setCursorPosition(m_selectionStart); m_styleName->insert(word); m_styleName->setFocus(); storeSelectionInfo(); } //------- // remember the selection of m_stylename when mouse entered in EasyInputArea void StyleNameEditor::storeSelectionInfo() { if (m_styleName->hasSelectedText()) { m_selectionStart = m_styleName->selectionStart(); m_selectionLength = m_styleName->selectedText().length(); } else { m_selectionStart = m_styleName->cursorPosition(); m_selectionLength = 0; } }