From 0ff1b687b06d9b81f578f1af8340f99148880a9d Mon Sep 17 00:00:00 2001 From: Jeremy Bullock Date: Oct 03 2017 08:15:33 +0000 Subject: Customize Command Bar and XSheet Toolbar (#1448) * Edit In Place added to Toolbars * Customize Command Bar and XSheet Toolbar --- diff --git a/stuff/profiles/layouts/rooms/Default/menubar_template.xml b/stuff/profiles/layouts/rooms/Default/menubar_template.xml index 56c209b..637efbf 100644 --- a/stuff/profiles/layouts/rooms/Default/menubar_template.xml +++ b/stuff/profiles/layouts/rooms/Default/menubar_template.xml @@ -125,6 +125,7 @@ MI_Resequence MI_CloneChild MI_ExplodeChild + MI_ToggleEditInPlace MI_ApplyMatchLines MI_MergeCmapped diff --git a/stuff/profiles/layouts/settings/commandbar.xml b/stuff/profiles/layouts/settings/commandbar.xml new file mode 100644 index 0000000..ef79a8f --- /dev/null +++ b/stuff/profiles/layouts/settings/commandbar.xml @@ -0,0 +1,19 @@ + + + MI_NewVectorLevel + MI_NewToonzRasterLevel + MI_NewRasterLevel + + MI_Reframe1 + MI_Reframe2 + MI_Reframe3 + + MI_Dup + + MI_Collapse + MI_OpenChild + MI_CloseChild + MI_ToggleEditInPlace + + + diff --git a/stuff/profiles/layouts/settings/xsheettoolbar.xml b/stuff/profiles/layouts/settings/xsheettoolbar.xml new file mode 100644 index 0000000..ef79a8f --- /dev/null +++ b/stuff/profiles/layouts/settings/xsheettoolbar.xml @@ -0,0 +1,19 @@ + + + MI_NewVectorLevel + MI_NewToonzRasterLevel + MI_NewRasterLevel + + MI_Reframe1 + MI_Reframe2 + MI_Reframe3 + + MI_Dup + + MI_Collapse + MI_OpenChild + MI_CloseChild + MI_ToggleEditInPlace + + + diff --git a/toonz/sources/include/toonz/childstack.h b/toonz/sources/include/toonz/childstack.h index 8981fe7..031c4c5 100644 --- a/toonz/sources/include/toonz/childstack.h +++ b/toonz/sources/include/toonz/childstack.h @@ -43,7 +43,6 @@ class DVAPI ChildStack { std::vector m_stack; TXsheet *m_xsheet; ToonzScene *m_scene; - bool m_editInPlace; public: /*! @@ -115,9 +114,6 @@ visibile in \b row. */ bool getAncestorAffine(TAffine &aff, int row) const; - bool getEditInPlace() const { return m_editInPlace; } - void setEditInPlace(bool editInPlace); - private: // not implemented ChildStack(const ChildStack &); diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index 5de78c0..e169bab 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -30,6 +30,7 @@ set(MOC_HEADERS columncommand.h columnselection.h commandbar.h + commandbarpopup.h convertpopup.h curveio.h drawingdata.h @@ -167,6 +168,7 @@ set(SOURCES floatingpanelcommand.cpp canvassizepopup.cpp commandbar.cpp + commandbarpopup.cpp history.cpp loadfoldercommand.cpp loadfolderpopup.cpp diff --git a/toonz/sources/toonz/Resources/edit_in_place.svg b/toonz/sources/toonz/Resources/edit_in_place.svg new file mode 100644 index 0000000..5190190 --- /dev/null +++ b/toonz/sources/toonz/Resources/edit_in_place.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/toonz/sources/toonz/castviewer.cpp b/toonz/sources/toonz/castviewer.cpp index ef776ba..78182bc 100644 --- a/toonz/sources/toonz/castviewer.cpp +++ b/toonz/sources/toonz/castviewer.cpp @@ -743,8 +743,8 @@ QMenu *CastBrowser::getContextMenu(QWidget *parent, int index) { levelSelectedCount++; if (sl->getType() == PLI_XSHLEVEL) vectorLevelSelected = true; - else if(sl->getType() == MESH_XSHLEVEL) - meshLevelSelected = true; + else if (sl->getType() == MESH_XSHLEVEL) + meshLevelSelected = true; else otherFileSelected = true; } @@ -755,8 +755,8 @@ QMenu *CastBrowser::getContextMenu(QWidget *parent, int index) { menu->addAction(cm->getAction(MI_ExposeResource)); menu->addAction(cm->getAction(MI_ShowFolderContents)); - if(!audioSelected && !paletteSelected && !meshLevelSelected) - menu->addAction(cm->getAction(MI_ViewFile)); + if (!audioSelected && !paletteSelected && !meshLevelSelected) + menu->addAction(cm->getAction(MI_ViewFile)); menu->addAction(cm->getAction(MI_FileInfo)); // MI_EditLevel solo se e' stato selezionato un singolo diverso da livelli diff --git a/toonz/sources/toonz/commandbar.cpp b/toonz/sources/toonz/commandbar.cpp index ceea7fb..75a5f96 100644 --- a/toonz/sources/toonz/commandbar.cpp +++ b/toonz/sources/toonz/commandbar.cpp @@ -1,21 +1,28 @@ - + #include "commandbar.h" // Tnz6 includes #include "tapp.h" #include "menubarcommandids.h" +#include "tsystem.h" +#include "commandbarpopup.h" + // TnzQt includes +#include "toonzqt/menubarcommand.h" #include "toonzqt/gutil.h" // TnzLib includes -#include "toonz/preferences.h" #include "toonz/tscenehandle.h" -#include "toonzqt/menubarcommand.h" - +#include "toonz/toonzscene.h" +#include "toonz/childstack.h" +#include "toonz/toonzfolders.h" // Qt includes #include - +#include +#include +#include +#include //============================================================================= // Toolbar @@ -23,62 +30,132 @@ #if QT_VERSION >= 0x050500 CommandBar::CommandBar(QWidget *parent, Qt::WindowFlags flags, - bool isCollapsible) + bool isCollapsible, bool isXsheetToolbar) #else -CommandBar::CommandBar(XsheetViewer *parent, Qt::WFlags flags) +CommandBar::CommandBar(QWidget *parent, Qt::WFlags flags) #endif : QToolBar(parent), m_isCollapsible(isCollapsible) { setObjectName("cornerWidget"); setObjectName("CommandBar"); + fillToolbar(this, isXsheetToolbar); +} + +//----------------------------------------------------------------------------- + +void CommandBar::fillToolbar(CommandBar *toolbar, bool isXsheetToolbar) { + toolbar->clear(); + TFilePath personalPath; + if (isXsheetToolbar) { + personalPath = + ToonzFolder::getMyModuleDir() + TFilePath("xsheettoolbar.xml"); + } else { + personalPath = ToonzFolder::getMyModuleDir() + TFilePath("commandbar.xml"); + } + if (!TSystem::doesExistFileOrLevel(personalPath)) { + if (isXsheetToolbar) { + personalPath = + ToonzFolder::getTemplateModuleDir() + TFilePath("xsheettoolbar.xml"); + } else { + personalPath = + ToonzFolder::getTemplateModuleDir() + TFilePath("commandbar.xml"); + } + } + QFile file(toQString(personalPath)); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + qDebug() << "Cannot read file" << file.errorString(); + buildDefaultToolbar(toolbar); + return; + } + + QXmlStreamReader reader(&file); + + if (reader.readNextStartElement()) { + if (reader.name() == "commandbar") { + while (reader.readNextStartElement()) { + if (reader.name() == "command") { + QString cmdName = reader.readElementText(); + std::string cmdStr = cmdName.toStdString(); + QAction *action = + CommandManager::instance()->getAction(cmdStr.c_str()); + if (action) toolbar->addAction(action); + } else if (reader.name() == "separator") { + toolbar->addSeparator(); + reader.skipCurrentElement(); + } else + reader.skipCurrentElement(); + } + } else + reader.raiseError(QObject::tr("Incorrect file")); + } else { + reader.raiseError(QObject::tr("Cannot Read XML File")); + } - TApp *app = TApp::instance(); - m_keyFrameButton = new ViewerKeyframeNavigator(this, app->getCurrentFrame()); - m_keyFrameButton->setObjectHandle(app->getCurrentObject()); - m_keyFrameButton->setXsheetHandle(app->getCurrentXsheet()); + if (reader.hasError()) { + buildDefaultToolbar(toolbar); + return; + } +} - QWidgetAction *keyFrameAction = new QWidgetAction(this); - keyFrameAction->setDefaultWidget(m_keyFrameButton); +//----------------------------------------------------------------------------- +void CommandBar::buildDefaultToolbar(CommandBar *toolbar) { + toolbar->clear(); + TApp *app = TApp::instance(); { QAction *newVectorLevel = CommandManager::instance()->getAction("MI_NewVectorLevel"); - addAction(newVectorLevel); + toolbar->addAction(newVectorLevel); QAction *newToonzRasterLevel = CommandManager::instance()->getAction("MI_NewToonzRasterLevel"); - addAction(newToonzRasterLevel); + toolbar->addAction(newToonzRasterLevel); QAction *newRasterLevel = CommandManager::instance()->getAction("MI_NewRasterLevel"); - addAction(newRasterLevel); - addSeparator(); + toolbar->addAction(newRasterLevel); + toolbar->addSeparator(); QAction *reframeOnes = CommandManager::instance()->getAction("MI_Reframe1"); - addAction(reframeOnes); + toolbar->addAction(reframeOnes); QAction *reframeTwos = CommandManager::instance()->getAction("MI_Reframe2"); - addAction(reframeTwos); + toolbar->addAction(reframeTwos); QAction *reframeThrees = CommandManager::instance()->getAction("MI_Reframe3"); - addAction(reframeThrees); + toolbar->addAction(reframeThrees); - addSeparator(); + toolbar->addSeparator(); QAction *repeat = CommandManager::instance()->getAction("MI_Dup"); - addAction(repeat); + toolbar->addAction(repeat); - addSeparator(); + toolbar->addSeparator(); QAction *collapse = CommandManager::instance()->getAction("MI_Collapse"); - addAction(collapse); + toolbar->addAction(collapse); QAction *open = CommandManager::instance()->getAction("MI_OpenChild"); - addAction(open); + toolbar->addAction(open); QAction *leave = CommandManager::instance()->getAction("MI_CloseChild"); - addAction(leave); - - addSeparator(); - addAction(keyFrameAction); + toolbar->addAction(leave); + QAction *editInPlace = + CommandManager::instance()->getAction("MI_ToggleEditInPlace"); + toolbar->addAction(editInPlace); } } +//----------------------------------------------------------------------------- +void CommandBar::contextMenuEvent(QContextMenuEvent *event) { + QMenu *menu = new QMenu(this); + QAction *customizeCommandBar = menu->addAction(tr("Customize Command Bar")); + connect(customizeCommandBar, SIGNAL(triggered()), + SLOT(doCustomizeCommandBar())); + menu->exec(event->globalPos()); +} +//----------------------------------------------------------------------------- +void CommandBar::doCustomizeCommandBar() { + CommandBarPopup *cbPopup = new CommandBarPopup(); - + if (cbPopup->exec()) { + fillToolbar(this); + } + delete cbPopup; +} \ No newline at end of file diff --git a/toonz/sources/toonz/commandbar.h b/toonz/sources/toonz/commandbar.h index 12262d7..5bf520a 100644 --- a/toonz/sources/toonz/commandbar.h +++ b/toonz/sources/toonz/commandbar.h @@ -6,7 +6,6 @@ #include #include "toonz/txsheet.h" -#include "toonz/txshleveltypes.h" #include "toonzqt/keyframenavigator.h" #include @@ -14,31 +13,34 @@ //----------------------------------------------------------------------------- // forward declaration -class XsheetViewer; -class QPushButton; +class QAction; //============================================================================= -// XSheet Toolbar +// CommandBar //----------------------------------------------------------------------------- -class CommandBar final : public QToolBar { +class CommandBar : public QToolBar { Q_OBJECT - - //XsheetViewer *m_viewer; - ViewerKeyframeNavigator *m_keyFrameButton; bool m_isCollapsible; public: #if QT_VERSION >= 0x050500 CommandBar(QWidget *parent = 0, Qt::WindowFlags flags = 0, - bool isCollapsible = false); + bool isCollapsible = false, bool isXsheetToolbar = false); #else - CommandBar(XsheetViewer *parent = 0, Qt::WFlags flags = 0); + CommandBar(QWidget *parent = 0, Qt::WFlags flags = 0); #endif - + signals: void updateVisibility(); - + +protected: + static void fillToolbar(CommandBar *toolbar, bool isXsheetToolbar = false); + static void buildDefaultToolbar(CommandBar *toolbar); + void contextMenuEvent(QContextMenuEvent *event) override; + +protected slots: + void doCustomizeCommandBar(); }; #endif // COMMANDBAR_H diff --git a/toonz/sources/toonz/commandbarpopup.cpp b/toonz/sources/toonz/commandbarpopup.cpp new file mode 100644 index 0000000..8d0a903 --- /dev/null +++ b/toonz/sources/toonz/commandbarpopup.cpp @@ -0,0 +1,480 @@ +#include "commandbarpopup.h" + +// Tnz includes +#include "tapp.h" +#include "menubar.h" +#include "shortcutpopup.h" + +// TnzQt includes +#include "toonzqt/gutil.h" + +// TnzLib includes +#include "toonz/toonzfolders.h" + +// TnzCore includes +#include "tsystem.h" + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//============================================================================= +// CommandBarCommandItem +//----------------------------------------------------------------------------- + +class CommandBarCommandItem final : public QTreeWidgetItem { + QAction* m_action; + +public: + CommandBarCommandItem(QTreeWidgetItem* parent, QAction* action) + : QTreeWidgetItem(parent, UserType), m_action(action) { + setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | + Qt::ItemNeverHasChildren); + setText(0, m_action->text().remove("&")); + setToolTip(0, QObject::tr("[Drag] to move position")); + } + QAction* getAction() const { return m_action; } +}; + +//============================================================================= +// CommandBarSeparatorItem +//----------------------------------------------------------------------------- + +class CommandBarSeparatorItem final : public QTreeWidgetItem { +public: + CommandBarSeparatorItem(QTreeWidgetItem* parent) + : QTreeWidgetItem(parent, UserType) { + setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | + Qt::ItemNeverHasChildren); + setText(0, QObject::tr("----Separator----")); + setToolTip(0, QObject::tr("[Drag] to move position")); + } +}; + +//============================================================================= +// CommandBarTree +//----------------------------------------------------------------------------- + +CommandBarTree::CommandBarTree(TFilePath& path, QWidget* parent) + : QTreeWidget(parent) { + setObjectName("SolidLineFrame"); + setAlternatingRowColors(true); + setDragEnabled(true); + setDropIndicatorShown(true); + setDefaultDropAction(Qt::MoveAction); + setDragDropMode(QAbstractItemView::DragDrop); + setIconSize(QSize(21, 17)); + + setColumnCount(1); + header()->close(); + + /*- Load path if it does exist. If not, then load from the template. -*/ + TFilePath fp; + if (TFileStatus(path).isWritable()) + fp = path; + else { + if (path.getName() == "xsheettoolbar") { + fp = ToonzFolder::getTemplateModuleDir() + TFilePath("xsheettoolbar.xml"); + } else { + fp = ToonzFolder::getTemplateModuleDir() + TFilePath("commandbar.xml"); + } + } + + loadMenuTree(fp); +} + +//----------------------------------------------------------------------------- + +void CommandBarTree::loadMenuTree(const TFilePath& fp) { + QFile file(toQString(fp)); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + qDebug() << "Cannot read file" << file.errorString(); + return; + } + + QXmlStreamReader reader(&file); + + if (reader.readNextStartElement()) { + if (reader.name() == "commandbar") { + while (reader.readNextStartElement()) { + if (reader.name() == "command") { + QString cmdName = reader.readElementText(); + + QAction* action = CommandManager::instance()->getAction( + cmdName.toStdString().c_str()); + if (action) { + CommandBarCommandItem* item = new CommandBarCommandItem(0, action); + addTopLevelItem(item); + } + } else if (reader.name() == "separator") { + CommandBarSeparatorItem* sep = new CommandBarSeparatorItem(0); + addTopLevelItem(sep); + reader.skipCurrentElement(); + } else + reader.skipCurrentElement(); + } + } else + reader.raiseError(QObject::tr("Incorrect file")); + } + + if (reader.hasError()) { + qDebug() << "Cannot read menubar xml"; + } +} + +//----------------------------------------------------------------------------- + +void CommandBarTree::loadMenuRecursive(QXmlStreamReader& reader, + QTreeWidgetItem* parentItem) { + while (reader.readNextStartElement()) { + if (reader.name() == "command") { + QString cmdName = reader.readElementText(); + QAction* action = + CommandManager::instance()->getAction(cmdName.toStdString().c_str()); + if (action) + CommandBarCommandItem* item = + new CommandBarCommandItem(parentItem, action); + } else if (reader.name() == "command_debug") { +#ifndef NDEBUG + QString cmdName = reader.readElementText(); + QAction* action = + CommandManager::instance()->getAction(cmdName.toStdString().c_str()); + if (action) + CommandBarCommandItem* item = + new CommandBarCommandItem(parentItem, action); +#else + reader.skipCurrentElement(); +#endif + } else if (reader.name() == "separator") { + CommandBarSeparatorItem* sep = new CommandBarSeparatorItem(parentItem); + reader.skipCurrentElement(); + } else + reader.skipCurrentElement(); + } +} + +//----------------------------------------------------------------------------- + +void CommandBarTree::saveMenuTree(TFilePath& path) { + QFile file(toQString(path)); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + qDebug() << "Cannot read file" << file.errorString(); + return; + } + + QXmlStreamWriter writer(&file); + writer.setAutoFormatting(true); + writer.writeStartDocument(); + + writer.writeStartElement("commandbar"); + { saveMenuRecursive(writer, invisibleRootItem()); } + writer.writeEndElement(); + + writer.writeEndDocument(); +} + +//----------------------------------------------------------------------------- + +void CommandBarTree::saveMenuRecursive(QXmlStreamWriter& writer, + QTreeWidgetItem* parentItem) { + for (int c = 0; c < parentItem->childCount(); c++) { + CommandBarCommandItem* command = + dynamic_cast(parentItem->child(c)); + CommandBarSeparatorItem* sep = + dynamic_cast(parentItem->child(c)); + + if (command) + writer.writeTextElement( + "command", + QString::fromStdString(CommandManager::instance()->getIdFromAction( + command->getAction()))); + else if (sep) + writer.writeEmptyElement("separator"); + } +} + +//----------------------------------------------------------------------------- + +bool CommandBarTree::dropMimeData(QTreeWidgetItem* parent, int index, + const QMimeData* data, + Qt::DropAction action) { + if (data->hasText()) { + QString txt = data->text(); + QTreeWidgetItem* item; + if (txt == "separator") + item = new CommandBarSeparatorItem(0); + else { + QAction* act = + CommandManager::instance()->getAction(txt.toStdString().c_str()); + if (!act) return false; + item = new CommandBarCommandItem(0, act); + } + + if (parent) + parent->insertChild(index, item); + else + insertTopLevelItem(index, item); + + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- + +QStringList CommandBarTree::mimeTypes() const { + QStringList qstrList; + qstrList.append("text/plain"); + return qstrList; +} + +//----------------------------------------------------------------------------- + +void CommandBarTree::contextMenuEvent(QContextMenuEvent* event) { + QTreeWidgetItem* item = itemAt(event->pos()); + if (item != currentItem()) setCurrentItem(item); + QMenu* menu = new QMenu(this); + QAction* action; + + if (item) { + action = menu->addAction(tr("Remove \"%1\"").arg(item->text(0))); + connect(action, SIGNAL(triggered()), this, SLOT(removeItem())); + } + + menu->exec(event->globalPos()); + delete menu; +} + +//----------------------------------------------------------------------------- + +void CommandBarTree::removeItem() { + QTreeWidgetItem* item = currentItem(); + if (!item) return; + + if (indexOfTopLevelItem(item) >= 0) + takeTopLevelItem(indexOfTopLevelItem(item)); + else + item->parent()->removeChild(item); + + delete item; +} + +//============================================================================= +// CommandListTree +//----------------------------------------------------------------------------- + +CommandBarListTree::CommandBarListTree(QWidget* parent) : QTreeWidget(parent) { + setObjectName("SolidLineFrame"); + setAlternatingRowColors(true); + setDragEnabled(true); + setDragDropMode(QAbstractItemView::DragOnly); + setColumnCount(1); + setIconSize(QSize(21, 17)); + header()->close(); + + QIcon menuFolderIcon(":Resources/browser_project_close.svg"); + menuFolderIcon.addFile(":Resources/browser_project_open.svg", QSize(), + QIcon::Normal, QIcon::On); + invisibleRootItem()->setIcon(0, menuFolderIcon); + + QTreeWidgetItem* menuCommandFolder = new QTreeWidgetItem(this); + menuCommandFolder->setFlags(Qt::ItemIsEnabled); + menuCommandFolder->setText(0, ShortcutTree::tr("Menu Commands")); + menuCommandFolder->setExpanded(true); + menuCommandFolder->setIcon(0, invisibleRootItem()->icon(0)); + + addFolder(ShortcutTree::tr("File"), MenuFileCommandType, menuCommandFolder); + addFolder(ShortcutTree::tr("Edit"), MenuEditCommandType, menuCommandFolder); + addFolder(ShortcutTree::tr("Scan & Cleanup"), MenuScanCleanupCommandType, + menuCommandFolder); + addFolder(ShortcutTree::tr("Level"), MenuLevelCommandType, menuCommandFolder); + addFolder(ShortcutTree::tr("Xsheet"), MenuXsheetCommandType, + menuCommandFolder); + addFolder(ShortcutTree::tr("Cells"), MenuCellsCommandType, menuCommandFolder); + addFolder(ShortcutTree::tr("View"), MenuViewCommandType, menuCommandFolder); + addFolder(ShortcutTree::tr("Windows"), MenuWindowsCommandType, + menuCommandFolder); + + addFolder(ShortcutTree::tr("Tools"), ToolCommandType); + addFolder(ShortcutTree::tr("Playback"), PlaybackCommandType); + addFolder(ShortcutTree::tr("Fill"), FillCommandType); + addFolder(ShortcutTree::tr("Right-click Menu Commands"), + RightClickMenuCommandType); + addFolder(ShortcutTree::tr("Tool Modifiers"), ToolModifierCommandType); + addFolder(ShortcutTree::tr("Visualization"), ZoomCommandType); + addFolder(ShortcutTree::tr("Misc"), MiscCommandType); + addFolder(ShortcutTree::tr("RGBA Channels"), RGBACommandType); + + CommandBarSeparatorItem* sep = new CommandBarSeparatorItem(0); + sep->setToolTip(0, QObject::tr("[Drag&Drop] to copy separator to menu bar")); + addTopLevelItem(sep); +} + +//----------------------------------------------------------------------------- + +void CommandBarListTree::addFolder(const QString& title, int commandType, + QTreeWidgetItem* parentFolder) { + QTreeWidgetItem* folder; + if (!parentFolder) + folder = new QTreeWidgetItem(this); + else + folder = new QTreeWidgetItem(parentFolder); + assert(folder); + folder->setText(0, title); + folder->setIcon(0, invisibleRootItem()->icon(0)); + + std::vector actions; + CommandManager::instance()->getActions((CommandType)commandType, actions); + for (int i = 0; i < (int)actions.size(); i++) { + CommandBarCommandItem* item = new CommandBarCommandItem(folder, actions[i]); + item->setToolTip(0, QObject::tr("[Drag&Drop] to copy command to menu bar")); + } +} + +//----------------------------------------------------------------------------- + +void CommandBarListTree::mousePressEvent(QMouseEvent* event) { + setCurrentItem(itemAt(event->pos())); + CommandBarCommandItem* commandItem = + dynamic_cast(itemAt(event->pos())); + CommandBarSeparatorItem* separatorItem = + dynamic_cast(itemAt(event->pos())); + + if (commandItem || separatorItem) { + std::string dragStr; + QString dragPixmapTxt; + if (commandItem) { + dragStr = + CommandManager::instance()->getIdFromAction(commandItem->getAction()); + dragPixmapTxt = commandItem->getAction()->text(); + dragPixmapTxt.remove("&"); + } else { + dragStr = "separator"; + dragPixmapTxt = tr("----Separator----"); + } + + QMimeData* mimeData = new QMimeData; + mimeData->setText(QString::fromStdString(dragStr)); + + QFontMetrics fm(QApplication::font()); + QPixmap pix(fm.boundingRect(dragPixmapTxt).adjusted(-2, -2, 2, 2).size()); + QPainter painter(&pix); + painter.fillRect(pix.rect(), Qt::white); + painter.setPen(Qt::black); + painter.drawText(pix.rect(), Qt::AlignCenter, dragPixmapTxt); + + QDrag* drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->setPixmap(pix); + + drag->exec(Qt::CopyAction); + } + + QTreeWidget::mousePressEvent(event); +} + +//============================================================================= +// CommandBarPopup +//----------------------------------------------------------------------------- + +CommandBarPopup::CommandBarPopup(bool isXsheetToolbar) + : Dialog(TApp::instance()->getMainWindow(), true, false, + "CustomizeCommandBar") { + QLabel* commandBarLabel; + if (isXsheetToolbar) { + m_path = ToonzFolder::getMyModuleDir() + TFilePath("xsheettoolbar.xml"); + commandBarLabel = new QLabel(tr("XSheet Toolbar")); + setWindowTitle(tr("Customize XSheet Toolbar")); + } else { + m_path = ToonzFolder::getMyModuleDir() + TFilePath("commandbar.xml"); + commandBarLabel = new QLabel(tr("Command Bar")); + setWindowTitle(tr("Customize Command Bar")); + } + + m_commandListTree = new CommandBarListTree(this); + m_menuBarTree = new CommandBarTree(m_path, this); + + QPushButton* okBtn = new QPushButton(tr("OK"), this); + QPushButton* cancelBtn = new QPushButton(tr("Cancel"), this); + + okBtn->setFocusPolicy(Qt::NoFocus); + cancelBtn->setFocusPolicy(Qt::NoFocus); + + QLabel* commandItemListLabel = new QLabel(tr("Toolbar Items"), this); + + QFont f("Arial", 15, QFont::Bold); + commandBarLabel->setFont(f); + commandItemListLabel->setFont(f); + + QLabel* noticeLabel = + new QLabel(tr("Duplicated commands will be ignored. Only " + "the last one will appear in the menu bar."), + this); + QFont nf("Arial", 9, QFont::Normal); + nf.setItalic(true); + noticeLabel->setFont(nf); + + //--- layout + QVBoxLayout* mainLay = new QVBoxLayout(); + m_topLayout->setMargin(0); + m_topLayout->setSpacing(0); + { + QGridLayout* mainUILay = new QGridLayout(); + mainUILay->setMargin(5); + mainUILay->setHorizontalSpacing(8); + mainUILay->setVerticalSpacing(5); + { + mainUILay->addWidget(commandBarLabel, 0, 0); + mainUILay->addWidget(commandItemListLabel, 0, 1); + mainUILay->addWidget(m_menuBarTree, 1, 0); + mainUILay->addWidget(m_commandListTree, 1, 1); + + mainUILay->addWidget(noticeLabel, 2, 0, 1, 2); + } + mainUILay->setRowStretch(0, 0); + mainUILay->setRowStretch(1, 1); + mainUILay->setRowStretch(2, 0); + mainUILay->setColumnStretch(0, 1); + mainUILay->setColumnStretch(1, 1); + + m_topLayout->addLayout(mainUILay, 1); + } + + m_buttonLayout->setMargin(0); + m_buttonLayout->setSpacing(30); + { + m_buttonLayout->addStretch(1); + m_buttonLayout->addWidget(okBtn, 0); + m_buttonLayout->addWidget(cancelBtn, 0); + m_buttonLayout->addStretch(1); + } + + //--- signal/slot connections + + bool ret = connect(okBtn, SIGNAL(clicked()), this, SLOT(onOkPressed())); + ret = ret && connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject())); + assert(ret); +} + +//----------------------------------------------------------------------------- + +void CommandBarPopup::onOkPressed() { + m_menuBarTree->saveMenuTree(m_path); + + accept(); +} \ No newline at end of file diff --git a/toonz/sources/toonz/commandbarpopup.h b/toonz/sources/toonz/commandbarpopup.h new file mode 100644 index 0000000..ac56c74 --- /dev/null +++ b/toonz/sources/toonz/commandbarpopup.h @@ -0,0 +1,73 @@ +#pragma once + +#ifndef COMMANDBARPOPUP_H +#define COMMANDBARPOPUP_H + +#include +#include +#include + +#include "toonzqt/dvdialog.h" +#include "tfilepath.h" + +class QXmlStreamReader; +class QXmlStreamWriter; + +//============================================================================= +// CommandBarTree +//----------------------------------------------------------------------------- + +class CommandBarTree final : public QTreeWidget { + Q_OBJECT + + void loadMenuTree(const TFilePath& fp); + void loadMenuRecursive(QXmlStreamReader& reader, QTreeWidgetItem* parentItem); + void saveMenuRecursive(QXmlStreamWriter& writer, QTreeWidgetItem* parentItem); + +public: + CommandBarTree(TFilePath& path, QWidget* parent = 0); + void saveMenuTree(TFilePath& path); + +protected: + bool dropMimeData(QTreeWidgetItem* parent, int index, const QMimeData* data, + Qt::DropAction action) override; + QStringList mimeTypes() const override; + void contextMenuEvent(QContextMenuEvent* event) override; +protected slots: + void removeItem(); +}; + +//============================================================================= +// CommandBarListTree +//----------------------------------------------------------------------------- + +class CommandBarListTree final : public QTreeWidget { + Q_OBJECT + + void addFolder(const QString& title, int commandType, + QTreeWidgetItem* parentFolder = 0); + +public: + CommandBarListTree(QWidget* parent = 0); + +protected: + void mousePressEvent(QMouseEvent*) override; +}; + +//============================================================================= +// CommandBarPopup +//----------------------------------------------------------------------------- + +class CommandBarPopup final : public DVGui::Dialog { + Q_OBJECT + CommandBarListTree* m_commandListTree; + CommandBarTree* m_menuBarTree; + TFilePath m_path; + +public: + CommandBarPopup(bool isXsheetToolbar = false); +protected slots: + void onOkPressed(); +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/toonz/levelsettingspopup.cpp b/toonz/sources/toonz/levelsettingspopup.cpp index 28b844e..b946671 100644 --- a/toonz/sources/toonz/levelsettingspopup.cpp +++ b/toonz/sources/toonz/levelsettingspopup.cpp @@ -1191,7 +1191,7 @@ public: if (!simpleLevels.size()) return; for (i = 0; i < simpleLevels.size(); i++) { - if (!(simpleLevels[i]->getType() & LEVELCOLUMN_XSHLEVEL)) continue; + if (!(simpleLevels[i]->getType() & LEVELCOLUMN_XSHLEVEL)) continue; TFilePath path = simpleLevels[i]->getPath(); path = simpleLevels[i]->getScene()->decodeFilePath(path); diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 95f3be5..a14fa28 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -31,6 +31,7 @@ #include "toonz/stylemanager.h" #include "toonz/tscenehandle.h" #include "toonz/toonzscene.h" +#include "toonz/txshleveltypes.h" // TnzBase includes #include "tenv.h" @@ -62,6 +63,7 @@ TEnv::IntVar ViewCameraToggleAction("ViewCameraToggleAction", 1); TEnv::IntVar ViewTableToggleAction("ViewTableToggleAction", 1); TEnv::IntVar FieldGuideToggleAction("FieldGuideToggleAction", 0); TEnv::IntVar ViewBBoxToggleAction("ViewBBoxToggleAction1", 1); +TEnv::IntVar EditInPlaceToggleAction("EditInPlaceToggleAction", 0); #ifdef LINETEST TEnv::IntVar CapturePanelFieldGuideToggleAction( "CapturePanelFieldGuideToggleAction", 0); @@ -1248,6 +1250,8 @@ void MainWindow::onMenuCheckboxChanged() { ViewCameraToggleAction = isChecked; else if (cm->getAction(MI_ViewTable) == action) ViewTableToggleAction = isChecked; + else if (cm->getAction(MI_ToggleEditInPlace) == action) + EditInPlaceToggleAction = isChecked; else if (cm->getAction(MI_ViewBBox) == action) ViewBBoxToggleAction = isChecked; else if (cm->getAction(MI_FieldGuide) == action) @@ -1784,7 +1788,11 @@ void MainWindow::defineActions() { collapseAction->setIconText("Collapse"); collapseAction->setIcon(createQIconOnOffPNG("collapse")); - createMenuXsheetAction(MI_ToggleEditInPlace, tr("Toggle Edit in Place"), ""); + toggle = createToggle(MI_ToggleEditInPlace, tr("&Toggle Edit In Place"), "", + EditInPlaceToggleAction ? 1 : 0, MenuViewCommandType); + toggle->setIconText(tr("Toggle Edit in Place")); + toggle->setIcon(QIcon(":Resources/edit_in_place.svg")); + createMenuXsheetAction(MI_SaveSubxsheetAs, tr("&Save Sub-xsheet As..."), ""); createMenuXsheetAction(MI_Resequence, tr("Resequence"), ""); createMenuXsheetAction(MI_CloneChild, tr("Clone Sub-xsheet"), ""); @@ -2349,9 +2357,9 @@ RecentFiles::~RecentFiles() {} void RecentFiles::addFilePath(QString path, FileType fileType) { QList files = - (fileType == Scene) - ? m_recentScenes - : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages; + (fileType == Scene) ? m_recentScenes : (fileType == Level) + ? m_recentLevels + : m_recentFlipbookImages; int i; for (i = 0; i < files.size(); i++) if (files.at(i) == path) files.removeAt(i); @@ -2476,9 +2484,9 @@ void RecentFiles::saveRecentFiles() { QList RecentFiles::getFilesNameList(FileType fileType) { QList files = - (fileType == Scene) - ? m_recentScenes - : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages; + (fileType == Scene) ? m_recentScenes : (fileType == Level) + ? m_recentLevels + : m_recentFlipbookImages; QList names; int i; for (i = 0; i < files.size(); i++) { @@ -2505,9 +2513,9 @@ void RecentFiles::refreshRecentFilesMenu(FileType fileType) { menu->setEnabled(false); else { CommandId clearActionId = - (fileType == Scene) - ? MI_ClearRecentScene - : (fileType == Level) ? MI_ClearRecentLevel : MI_ClearRecentImage; + (fileType == Scene) ? MI_ClearRecentScene : (fileType == Level) + ? MI_ClearRecentLevel + : MI_ClearRecentImage; menu->setActions(names); menu->addSeparator(); QAction *clearAction = CommandManager::instance()->getAction(clearActionId); diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 4d68975..0d8b597 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1218,6 +1218,7 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { addMenuItem(xsheetMenu, MI_Resequence); addMenuItem(xsheetMenu, MI_CloneChild); addMenuItem(xsheetMenu, MI_ExplodeChild); + addMenuItem(xsheetMenu, MI_ToggleEditInPlace); xsheetMenu->addSeparator(); addMenuItem(xsheetMenu, MI_ApplyMatchLines); addMenuItem(xsheetMenu, MI_MergeCmapped); diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index e63e27a..b0153ed 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -278,6 +278,7 @@ void ToggleCommandHandler::execute() { //----------------------------------------------------------------------------- ToggleCommandHandler viewTableToggle(MI_ViewTable, false); +ToggleCommandHandler editInPlaceToggle(MI_ToggleEditInPlace, false); ToggleCommandHandler fieldGuideToggle(MI_FieldGuide, false); ToggleCommandHandler safeAreaToggle(MI_SafeArea, false); ToggleCommandHandler rasterizePliToggle(MI_RasterizePli, false); @@ -1587,8 +1588,8 @@ void SceneViewer::drawScene() { clipRect += TPoint(width() * 0.5, height() * 0.5); ChildStack *childStack = scene->getChildStack(); - bool editInPlace = - childStack->getEditInPlace() && !app->getCurrentFrame()->isEditingLevel(); + bool editInPlace = editInPlaceToggle.getStatus() && + !app->getCurrentFrame()->isEditingLevel(); bool fillFullColorRaster = TXshSimpleLevel::m_fillFullColorRaster; TXshSimpleLevel::m_fillFullColorRaster = false; diff --git a/toonz/sources/toonz/subscenecommand.cpp b/toonz/sources/toonz/subscenecommand.cpp index 07ab17f..c3cc040 100644 --- a/toonz/sources/toonz/subscenecommand.cpp +++ b/toonz/sources/toonz/subscenecommand.cpp @@ -1071,19 +1071,6 @@ void closeSubXsheet(int dlevel) { //============================================================================= -void toggleEditInPlace() { - TApp *app = TApp::instance(); - ToonzScene *scene = app->getCurrentScene()->getScene(); - int ancestorCount = scene->getChildStack()->getAncestorCount(); - if (ancestorCount == 0) return; - scene->getChildStack()->setEditInPlace( - !scene->getChildStack()->getEditInPlace()); - /*- Notify the change in order to update the viewer -*/ - app->instance()->getCurrentXsheet()->notifyXsheetChanged(); -} - -//============================================================================= - void bringPegbarsInsideChildXsheet(TXsheet *xsh, TXsheet *childXsh) { // retrieve all pegbars used from copied columns std::set pegbarIds; @@ -2115,16 +2102,6 @@ public: } closeChildCommand; //============================================================================= -// ToggleEditInPlaceCommand -//----------------------------------------------------------------------------- - -class ToggleEditInPlaceCommand final : public MenuItemHandler { -public: - ToggleEditInPlaceCommand() : MenuItemHandler(MI_ToggleEditInPlace) {} - void execute() override { toggleEditInPlace(); } -} toggleEditInPlaceCommand; - -//============================================================================= // collapseColumns //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index a199c33..b76e317 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -72,6 +72,7 @@ Resources/desktop.svg Resources/downTitle.png Resources/edit.svg + Resources/edit_in_place.svg Resources/edit_rollover.svg Resources/emptychip.png Resources/eraser.png diff --git a/toonz/sources/toonz/xshtoolbar.cpp b/toonz/sources/toonz/xshtoolbar.cpp index eafafb5..f750479 100644 --- a/toonz/sources/toonz/xshtoolbar.cpp +++ b/toonz/sources/toonz/xshtoolbar.cpp @@ -1,21 +1,18 @@ - - #include "xshtoolbar.h" // Tnz6 includes #include "xsheetviewer.h" #include "tapp.h" #include "menubarcommandids.h" -// TnzQt includes -#include "toonzqt/gutil.h" +#include "commandbarpopup.h" // TnzLib includes #include "toonz/preferences.h" +#include "toonz/toonzscene.h" #include "toonz/tscenehandle.h" -#include "toonzqt/menubarcommand.h" +#include "toonz/childstack.h" // Qt includes -#include #include //============================================================================= @@ -32,60 +29,12 @@ XSheetToolbar::XSheetToolbar(XsheetViewer *parent, Qt::WindowFlags flags, #else XSheetToolbar::XSheetToolbar(XsheetViewer *parent, Qt::WFlags flags) #endif - : QToolBar(parent), m_viewer(parent), m_isCollapsible(isCollapsible) { + : CommandBar(parent, flags, isCollapsible, true) + , m_viewer(parent) + , m_isCollapsible(isCollapsible) { setObjectName("cornerWidget"); setFixedHeight(30); setObjectName("XSheetToolbar"); - - TApp *app = TApp::instance(); - m_keyFrameButton = new ViewerKeyframeNavigator(this, app->getCurrentFrame()); - m_keyFrameButton->setObjectHandle(app->getCurrentObject()); - m_keyFrameButton->setXsheetHandle(app->getCurrentXsheet()); - - QWidgetAction *keyFrameAction = new QWidgetAction(this); - keyFrameAction->setDefaultWidget(m_keyFrameButton); - - { - QAction *newVectorLevel = - CommandManager::instance()->getAction("MI_NewVectorLevel"); - addAction(newVectorLevel); - QAction *newToonzRasterLevel = - CommandManager::instance()->getAction("MI_NewToonzRasterLevel"); - addAction(newToonzRasterLevel); - QAction *newRasterLevel = - CommandManager::instance()->getAction("MI_NewRasterLevel"); - addAction(newRasterLevel); - addSeparator(); - QAction *reframeOnes = CommandManager::instance()->getAction("MI_Reframe1"); - addAction(reframeOnes); - QAction *reframeTwos = CommandManager::instance()->getAction("MI_Reframe2"); - addAction(reframeTwos); - QAction *reframeThrees = - CommandManager::instance()->getAction("MI_Reframe3"); - addAction(reframeThrees); - - addSeparator(); - - QAction *repeat = CommandManager::instance()->getAction("MI_Dup"); - addAction(repeat); - - addSeparator(); - - QAction *collapse = CommandManager::instance()->getAction("MI_Collapse"); - addAction(collapse); - QAction *open = CommandManager::instance()->getAction("MI_OpenChild"); - addAction(open); - QAction *leave = CommandManager::instance()->getAction("MI_CloseChild"); - addAction(leave); - - addSeparator(); - addAction(keyFrameAction); - - if (!Preferences::instance()->isShowXSheetToolbarEnabled() && - m_isCollapsible) { - hide(); - } - } } //----------------------------------------------------------------------------- @@ -113,6 +62,28 @@ void XSheetToolbar::showEvent(QShowEvent *e) { emit updateVisibility(); } +//----------------------------------------------------------------------------- + +void XSheetToolbar::contextMenuEvent(QContextMenuEvent *event) { + QMenu *menu = new QMenu(this); + QAction *customizeCommandBar = + menu->addAction(tr("Customize XSheet Toolbar")); + connect(customizeCommandBar, SIGNAL(triggered()), + SLOT(doCustomizeCommandBar())); + menu->exec(event->globalPos()); +} + +//----------------------------------------------------------------------------- + +void XSheetToolbar::doCustomizeCommandBar() { + CommandBarPopup *cbPopup = new CommandBarPopup(true); + + if (cbPopup->exec()) { + fillToolbar(this, true); + } + delete cbPopup; +} + //============================================================ class ToggleXSheetToolbarCommand final : public MenuItemHandler { diff --git a/toonz/sources/toonz/xshtoolbar.h b/toonz/sources/toonz/xshtoolbar.h index 0ca8690..5437fdb 100644 --- a/toonz/sources/toonz/xshtoolbar.h +++ b/toonz/sources/toonz/xshtoolbar.h @@ -6,17 +6,16 @@ #include #include "toonz/txsheet.h" -#include "toonz/txshleveltypes.h" +#include "commandbar.h" #include "toonzqt/keyframenavigator.h" -#include #include //----------------------------------------------------------------------------- // forward declaration class XsheetViewer; -class QPushButton; +class QAction; //----------------------------------------------------------------------------- @@ -26,11 +25,10 @@ namespace XsheetGUI { // XSheet Toolbar //----------------------------------------------------------------------------- -class XSheetToolbar final : public QToolBar { +class XSheetToolbar final : public CommandBar { Q_OBJECT XsheetViewer *m_viewer; - ViewerKeyframeNavigator *m_keyFrameButton; bool m_isCollapsible; public: @@ -47,6 +45,10 @@ signals: protected: void showEvent(QShowEvent *e) override; + void contextMenuEvent(QContextMenuEvent *event) override; + +protected slots: + void doCustomizeCommandBar(); }; } // namespace XsheetGUI; diff --git a/toonz/sources/toonzlib/childstack.cpp b/toonz/sources/toonzlib/childstack.cpp index 2e1af15..587e791 100644 --- a/toonz/sources/toonzlib/childstack.cpp +++ b/toonz/sources/toonzlib/childstack.cpp @@ -32,7 +32,7 @@ public: // ChildStack ChildStack::ChildStack(ToonzScene *scene) - : m_scene(scene), m_xsheet(new TXsheet()), m_editInPlace(false) { + : m_scene(scene), m_xsheet(new TXsheet()) { m_xsheet->setScene(m_scene); m_xsheet->addRef(); } @@ -177,9 +177,3 @@ bool ChildStack::getAncestorAffine(TAffine &aff, int row) const { } return true; } - -//----------------------------------------------------------------------------- - -void ChildStack::setEditInPlace(bool editInPlace) { - m_editInPlace = editInPlace; -}