/* For general Scribus (>=1.3.2) copyright and licensing information please refer to the COPYING file provided with the program. Following this notice may exist a copyright and/or license notice that predates the release of Scribus 1.3.2 for which a new license (GPL+exception) is in place. */ #include #include #include #include #include #include "prefsmanager.h" #include "prefsfile.h" #include "commonstrings.h" #include "scribusdoc.h" #include "scribusview.h" #include "stylemanager.h" #include "shortcutwidget.h" #include "styleview.h" #include "styleitem.h" #include "smreplacedia.h" #include "selection.h" #include "customfdialog.h" #include "smtextstyles.h" #include "smlinestyle.h" #include "smlinestylewidget.h" #include "smstyleimport.h" #include "fileloader.h" #include "scraction.h" const QString StyleManager::SEPARATOR = "$$$$"; // dumb but it works StyleManager::StyleManager(QWidget *parent, const char *name) : ScrPaletteBase(parent, name), m_item(0), m_widget(0), m_shortcutWidget(0), m_currentType(QString::null), m_isEditMode(true), m_doc(0) { setupUi(this); styleView->hideColumn(SHORTCUT_COL); styleView->setSelectionMode(QAbstractItemView::ExtendedSelection); uniqueLabel->hide(); rightFrame->hide(); applyButton->setEnabled(false); resetButton->setEnabled(false); m_layout = new QGridLayout(mainFrame); m_newPopup = new QMenu(newButton); m_rightClickPopup = new QMenu(styleView); newButton->setMenu(m_newPopup); QString pname(name); if (pname.isEmpty()) pname = "styleManager"; m_prefs = PrefsManager::instance()->prefsFile->getContext(pname); m_isEditMode = true; m_isStoryEditMode = false; m_editPosition.setX(m_prefs->getInt("eX", x())); m_editPosition.setY(m_prefs->getInt("eY", y())); newButton->setEnabled(false); cloneButton->setEnabled(false); importButton->setEnabled(false); deleteButton->setEnabled(false); m_rightClickPopup->setEnabled(false); m_newPopup->setEnabled(false); m_selectedStyleAction = 0; connect(m_newPopup, SIGNAL(triggered(QAction*)), this, SLOT(slotNewPopup(QAction*))); connect(okButton, SIGNAL(clicked()), this, SLOT(slotOk())); connect(importButton, SIGNAL(clicked()), this, SLOT(slotImport())); connect(resetButton, SIGNAL(clicked()), this, SLOT(slotClean())); connect(applyButton, SIGNAL(clicked()), this, SLOT(slotApply())); connect(deleteButton, SIGNAL(clicked()), this, SLOT(slotDelete())); connect(cloneButton, SIGNAL(clicked()), this, SLOT(slotClone())); connect(newButton, SIGNAL(clicked()), this, SLOT(slotNew())); connect(styleView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotRightClick(const QPoint &))); connect(styleView, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotDoubleClick(QTreeWidgetItem *, int))); languageChange(); slotOk(); } void StyleManager::changeEvent(QEvent *e) { if (e->type() == QEvent::LanguageChange) { languageChange(); } else QWidget::changeEvent(e); } void StyleManager::languageChange() { setWindowTitle( tr( "Style Manager" ) ); /***********************************/ /* Begin Tooltips */ /***********************************/ // These are for general Style Manager widgets (not for c/pstyles except the name field // for the "<< Done" button when in edit mode m_exitEditModeOk = tr("Apply all changes and exit edit mode"); // for the "Edit >>" button when not in edit mode m_enterEditModeOk= tr("Edit styles"); nameEdit->setToolTip( tr("Name of the selected style")); resetButton->setToolTip( tr("Reset all changes")); applyButton->setToolTip( tr("Apply all changes")); newButton->setToolTip( tr("Create a new style")); importButton->setToolTip( tr("Import styles from another document")); cloneButton->setToolTip( tr("Clone selected style")); deleteButton->setToolTip( tr("Delete selected styles")); /***********************************/ /* End Tooltips */ /***********************************/ nameLabel->setText( tr("Name:")); resetButton->setText( tr("&Reset")); applyButton->setText( tr("&Apply")); m_doneText= tr("&Done"); m_editText= tr("&Edit"); setOkButtonText(); newButton->setText( tr("&New")); importButton->setText( tr("&Import")); cloneButton->setText( tr("&Clone")); deleteButton->setText( tr("&Delete")); if (m_isEditMode) okButton->setToolTip( m_exitEditModeOk); else okButton->setToolTip( m_enterEditModeOk); if (m_shortcutWidget) m_shortcutWidget->languageChange(); m_newPopup->clear(); QStringList popupStrings; for (int i = 0; i < m_items.count(); ++i) { popupStrings << m_items.at(i)->typeNameSingular(); m_items.at(i)->languageChange(); m_styleClassesPS[m_items.at(i)->typeNamePlural()] = m_items.at(i)->typeNameSingular(); m_styleClassesSP[m_items.at(i)->typeNameSingular()] = m_items.at(i)->typeNamePlural(); } popupStrings.sort(); for (int i = 0; i < popupStrings.count(); ++i) m_newPopup->addAction(popupStrings[i]); styleView->clear(); for (int i = 0; i < m_items.count(); ++i) addNewType(m_items.at(i)); styleView->resizeColumnToContents(0); m_rightClickPopup->clear(); m_rcpNewId = m_rightClickPopup->addMenu(m_newPopup); m_rcpNewId->setText( tr("New")); m_rightClickPopup->addAction( tr("Import"), this, SLOT(slotImport())); m_rightClickPopup->addSeparator(); m_rcpEditId = m_rightClickPopup->addAction( tr("Edit"), this, SLOT(slotEdit())); m_rcpCloneId = m_rightClickPopup->addAction( tr("Clone"), this, SLOT(slotClone())); // m_rcpToScrapId = m_rightClickPopup->addAction( tr("Send to Scrapbook"), this, SLOT(slotScrap())); m_rightClickPopup->addSeparator(); m_rcpDeleteId = m_rightClickPopup->addAction( tr("Delete"), this, SLOT(slotDelete())); } void StyleManager::unitChange() { if (m_doc) { for (int i = 0; i < m_items.count(); ++i) m_items.at(i)->unitChange(); slotSetupWidget(); } } void StyleManager::setOkButtonText() { if (!m_isStoryEditMode) okButton->setText(m_isEditMode ? "<< " + m_doneText : m_editText + " >>"); else okButton->setText(CommonStrings::tr_OK); } void StyleManager::setDoc(ScribusDoc *doc) { ScribusDoc* oldDoc = m_doc; bool hasDoc = (doc != NULL); if (m_doc && (m_doc != doc)) disconnect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(slotDocSelectionChanged())); m_doc = doc; newButton->setEnabled(hasDoc); cloneButton->setEnabled(hasDoc); importButton->setEnabled(hasDoc); deleteButton->setEnabled(hasDoc); m_rightClickPopup->setEnabled(hasDoc); m_newPopup->setEnabled(hasDoc); if (m_doc && (m_doc != oldDoc) && this->isVisible()) connect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(slotDocSelectionChanged())); // clear the style list and reload from new doc styleView->clear(); if (m_selectedStyleAction) { m_rightClickPopup->removeAction(m_selectedStyleAction); m_selectedStyleAction = 0; } m_styleActions.clear(); for (int i = 0; i < m_items.count(); ++i) { m_items.at(i)->setCurrentDoc(doc); addNewType(m_items.at(i)); // forces a reload if (m_doc) m_items.at(i)->unitChange(); } styleView->resizeColumnToContents(0); } void StyleManager::updateColorList() { for (int i = 0; i < m_items.count(); ++i) { m_items.at(i)->setCurrentDoc(m_doc); m_items.at(i)->reload(); } } void StyleManager::addStyle(StyleItem *item) { m_items.append(item); addNewType(item); languageChange(); // upgrade the popup menu with the new item connect(item, SIGNAL(selectionDirty()), this, SLOT(slotDirty())); } void StyleManager::slotApply() { if (applyButton->isEnabled()) { for (int i = 0; i < m_items.count(); ++i) m_items.at(i)->apply(); if (m_doc) m_doc->view()->DrawNew(); } slotClean(); } void StyleManager::slotDelete() { if (!m_isEditMode) slotOk(); // switch to edit mode before deleting QStringList selected; if (!m_rcStyle.isNull()) selected << m_rcStyle; else { QTreeWidgetItemIterator it(styleView, QTreeWidgetItemIterator::Selected); while (*it) { selected << (*it)->text(0); ++it; } } if (!m_item || selected.isEmpty()) return; // nothing to delete QStringList tmp; QList styles = m_item->styles(false); // get list from cache for (int i = 0; i < styles.count(); ++i) tmp << styles[i].first; SMReplaceDia dia(selected, tmp, this); if (dia.exec() && m_item) { m_item->deleteStyles(dia.items()); applyButton->setEnabled(true); resetButton->setEnabled(true); reloadStyleView(false); } } void StyleManager::slotImport() { if (!m_doc) return; PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs"); QString wdir = dirs->get("editformats", "."); CustomFDialog dia(this, wdir, tr("Open"), tr("documents (*.sla *.sla.gz *.scd *.scd.gz);;All Files (*)")); if (dia.exec() == QDialog::Accepted) { QString selectedFile = dia.selectedFile(); dirs->set("editformats", selectedFile.left(selectedFile.lastIndexOf("/"))); StyleSet tmpParaStyles; StyleSet tmpCharStyles; QMap tmpLineStyles; m_doc->loadStylesFromFile(selectedFile, &tmpParaStyles, &tmpCharStyles, &tmpLineStyles); // FIXME Once all styles are derived from Style remove this and make a proper // implementation // Start hack SMParagraphStyle *pstyle = 0; SMCharacterStyle *cstyle = 0; SMLineStyle *lstyle = 0; for (int i = 0; i < m_items.count(); ++i) { pstyle = dynamic_cast(m_items.at(i)); if (pstyle) break; } for (int i = 0; i < m_items.count(); ++i) { cstyle = dynamic_cast(m_items.at(i)); if (cstyle) break; } for (int i = 0; i < m_items.count(); ++i) { lstyle = dynamic_cast(m_items.at(i)); if (lstyle) break; } Q_ASSERT(pstyle && cstyle && lstyle); SMStyleImport *dia2 = new SMStyleImport(this, &tmpParaStyles, &tmpCharStyles, &tmpLineStyles); // end hack //#7315 QList > selected; if (dia2->exec()) { //#7385 if (!m_isEditMode) //#7385 slotOk(); QStringList neededColors; neededColors.clear(); foreach (QString aStyle, dia2->paragraphStyles()) { ParagraphStyle& sty(tmpParaStyles[tmpParaStyles.find(aStyle)]); if (dia2->clashRename()) { sty.setName(pstyle->getUniqueName(sty.name())); pstyle->tmpStyles()->create(sty); } else { if (pstyle->tmpStyles()->find(sty.name()) >= 0) (*(pstyle->tmpStyles()))[pstyle->tmpStyles()->find(/*it.data()*/aStyle)] = sty; else pstyle->tmpStyles()->create(sty); } //#7315 selected << QPair(pstyle->typeName(), sty.name()); if ((!m_doc->PageColors.contains(sty.charStyle().strokeColor())) && (!neededColors.contains(sty.charStyle().strokeColor()))) neededColors.append(sty.charStyle().strokeColor()); if ((!m_doc->PageColors.contains(sty.charStyle().fillColor())) && (!neededColors.contains(sty.charStyle().fillColor()))) neededColors.append(sty.charStyle().fillColor()); } foreach (QString aStyle, dia2->characterStyles()) { CharStyle& sty(tmpCharStyles[tmpCharStyles.find(/*it.data()*/aStyle)]); if (dia2->clashRename()) { sty.setName(cstyle->getUniqueName(sty.name())); cstyle->tmpStyles()->create(sty); } else { if (cstyle->tmpStyles()->find(sty.name()) >= 0) (*(cstyle->tmpStyles()))[cstyle->tmpStyles()->find(/*it.data()*/aStyle)] = sty; else cstyle->tmpStyles()->create(sty); } //#7315 selected << QPair(cstyle->typeName(), sty.name()); if ((!m_doc->PageColors.contains(sty.strokeColor())) && (!neededColors.contains(sty.strokeColor()))) neededColors.append(sty.strokeColor()); if ((!m_doc->PageColors.contains(sty.fillColor())) && (!neededColors.contains(sty.fillColor()))) neededColors.append(sty.fillColor()); } foreach (QString aStyle, dia2->lineStyles()) { multiLine &sty = tmpLineStyles[/*it.data()*/aStyle]; QString styName = aStyle; if (dia2->clashRename()) styName = lstyle->getUniqueName(aStyle); lstyle->tmpLines[styName] = sty; //#7315 selected << QPair(lstyle->typeName(), styName); for (int i = 0; i < sty.count(); ++i) { if ((!m_doc->PageColors.contains(sty[i].Color)) && (!neededColors.contains(sty[i].Color))) neededColors.append(sty[i].Color); } } if (!neededColors.isEmpty()) { FileLoader fl(selectedFile); if (fl.TestFile() == -1) { //TODO put in nice user warning delete dia2; return; } ColorList LColors; if (fl.ReadColors(selectedFile, LColors)) { ColorList::Iterator itc; for (itc = LColors.begin(); itc != LColors.end(); ++itc) { if (neededColors.contains(itc.key())) m_doc->PageColors.insert(itc.key(), itc.value()); } } } } delete dia2; // Start hack part 2 pstyle->setCurrentDoc(m_doc); cstyle->setCurrentDoc(m_doc); // end hack part 2 reloadStyleView(false); //#7315 setSelection(selected); slotDirty(); //#7315 slotSetupWidget(); slotApply();//#7315 } else return; } void StyleManager::setSelection(const QList > &selected) { styleView->clearSelection(); QTreeWidgetItemIterator it(styleView, QTreeWidgetItemIterator::Selectable); StyleViewItem *item; while (*it) { item = dynamic_cast(*it); if (item) { for (int i = 0; i < selected.count(); ++i) { if (item->rootName() == selected[i].first && item->text(NAME_COL) == selected[i].second) { styleView->setCurrentItem(item); item->setSelected(true); } } } ++it; } } void StyleManager::slotEdit() { if (!m_isEditMode) slotOk(); // switch to edit mode for cloning if (!m_rcStyle.isNull()) { QTreeWidgetItemIterator it(styleView); while (*it) { StyleViewItem *item = dynamic_cast(*it); if (item && !item->isRoot()) { if (item->rootName() == m_styleClassesSP[m_rcType] && item->text(0) == m_rcStyle) { styleView->setCurrentItem(item); item->setSelected(true); break; } } ++it; } m_rcStyle = QString::null; m_rcType = QString::null; } } void StyleManager::slotClone() { if (!m_isEditMode) slotOk(); // switch to edit mode for cloning if (!m_rcStyle.isNull()) { QTreeWidgetItemIterator it(styleView); while (*it) { StyleViewItem *item = dynamic_cast(*it); if (item && !item->isRoot()) { if (item->rootName() == m_styleClassesSP[m_rcType] && item->text(0) == m_rcStyle) { styleView->setCurrentItem(item); item->setSelected(true); break; } } ++it; } m_rcStyle = QString::null; m_rcType = QString::null; } QTreeWidgetItemIterator it(styleView, QTreeWidgetItemIterator::Selected); QList > names; while (*it) { // can't create styles here cause createNewStyle() alters the selection StyleViewItem *item = dynamic_cast(*it); if (item && !item->isRoot()) names << QPair(item->rootName(), item->text(NAME_COL)); ++it; } for (int i = 0; i < names.count(); ++i) createNewStyle(names[i].first, names[i].second); } void StyleManager::slotScrap() { } void StyleManager::slotNew() { //#5334: Dont open into edit mdoe until user has selected a style type // if (!m_isEditMode) // slotOk(); // switch to edit mode for a new style // TODO maybe there's something more clever for this m_newPopup->exec(newButton->mapToGlobal(QPoint(0, newButton->height() + 2))); } void StyleManager::slotNewPopup(QAction *i) { if (!m_isEditMode) slotOk(); // switch to edit mode for a new style QString typeName = m_rcType; if (typeName.isNull()) typeName = i->text(); else if (i->text().isNull()) return; m_rcType = QString::null; m_rcStyle = QString::null; createNewStyle(typeName); } void StyleManager::slotNewPopup() { slotNewPopup(m_rcpNewId); } void StyleManager::slotRightClick(/*StyleViewItem *item, */const QPoint &point/*, int col*/) { StyleViewItem *item = static_cast(styleView->currentItem()); m_rcStyle = QString::null; m_rcType = QString::null; if (m_isEditMode && item) // make item the only selection if in edit mode { // default behaviour for right clicking is not to select the item styleView->clearSelection(); styleView->setCurrentItem(item); item->setSelected(true); } if (item && !item->isRoot()) { m_rightClickPopup->removeAction(m_rcpNewId); m_rcpNewId = m_rightClickPopup->addAction( tr("New %1").arg(m_styleClassesPS[item->rootName()]), this, SLOT(slotNewPopup())); m_rcpDeleteId->setEnabled(true); m_rcpEditId->setEnabled(true); m_rcpCloneId->setEnabled(true); // m_rcpToScrapId->setEnabled(true); m_rcStyle = item->text(0); m_rcType = m_styleClassesPS[item->rootName()]; loadType(m_styleClassesPS[item->rootName()]); // Add "Apply" menu entry if(m_selectedStyleAction) { m_rightClickPopup->removeAction(m_selectedStyleAction); m_selectedStyleAction = 0; } if(styleView->selectedItems().count() == 1) { QString key = item->rootName() + SEPARATOR + item->text(NAME_COL); if(m_styleActions.contains(key)) { m_selectedStyleAction = m_styleActions[key]; if(m_selectedStyleAction) { m_rightClickPopup->insertAction( m_rightClickPopup->actions().first(), m_selectedStyleAction); } } } } else if (item && item->isRoot()) { m_rightClickPopup->removeAction(m_rcpNewId); m_rcpNewId = m_rightClickPopup->addAction( tr("New %1").arg(m_styleClassesPS[item->text(0)]), this, SLOT(slotNewPopup())); m_rcpDeleteId->setEnabled(false); m_rcpEditId->setEnabled(false); m_rcpCloneId->setEnabled(false); // m_rcpToScrapId->setEnabled(false); m_rcType = m_styleClassesPS[item->text(0)]; loadType(m_rcType); if(m_selectedStyleAction) { m_rightClickPopup->removeAction(m_selectedStyleAction); m_selectedStyleAction = 0; } } else { m_rightClickPopup->removeAction(m_rcpNewId); m_rcpNewId = m_rightClickPopup->addMenu(m_newPopup); m_rcpNewId->setText( tr("New")); m_rcpDeleteId->setEnabled(false); m_rcpEditId->setEnabled(false); m_rcpCloneId->setEnabled(false); // m_rcpToScrapId->setEnabled(false); if(m_selectedStyleAction) { m_rightClickPopup->removeAction(m_selectedStyleAction); m_selectedStyleAction = 0; } } m_rightClickPopup->exec(styleView->mapToGlobal(point)); } void StyleManager::slotDoubleClick(QTreeWidgetItem *item, /*const QPoint &point, */int col) { m_rcStyle = QString::null; m_rcType = QString::null; if (m_isEditMode && item) // make item the only selection if in edit mode { styleView->clearSelection(); styleView->setCurrentItem(item); item->setSelected(true); return; // work done, already in edit mode } StyleViewItem *sitem = dynamic_cast(item); if (sitem && !sitem->isRoot()) { m_rcType = m_styleClassesPS[sitem->rootName()]; m_rcStyle = sitem->text(0); slotEdit(); // switch to edit mode } else if (sitem && sitem->isRoot()) { //slotOk will recreate all items so sitem is invalid after that call QString itext = sitem->text(0); if (!m_isEditMode) slotOk(); createNewStyle(itext); } m_rcStyle = QString::null; m_rcType = QString::null; } void StyleManager::createNewStyle(const QString &typeName, const QString &fromParent) { if (!m_doc) return; loadType(typeName); // get the right style class Q_ASSERT(m_item); QString newName = fromParent.isNull() ? m_item->newStyle() : m_item->newStyle(fromParent); // qDebug() << "created new style:" << newName << " : " << m_item->isDefaultStyle(newName); if (newName.isNull()) return; StyleViewItem *root = 0; QTreeWidgetItemIterator it(styleView, QTreeWidgetItemIterator::NotSelectable); while (*it) { StyleViewItem *item = dynamic_cast(*it); if (item) { if (item->text(NAME_COL) == m_item->typeName()) { root = item; break; } } ++it; } assert(root); if (!fromParent.isEmpty()) { QTreeWidgetItemIterator it(root, QTreeWidgetItemIterator::Selectable); while (*it) { StyleViewItem *item = dynamic_cast(*it); if (item && item->text(NAME_COL) == fromParent) { StyleViewItem *parent = dynamic_cast((*it)->parent()); if (parent) { root = parent; break; } } ++it; } } styleView->clearSelection(); StyleViewItem *newItem = new StyleViewItem(root, newName, m_item->typeName()); Q_CHECK_PTR(newItem); newItem->setDirty(true); styleView->setCurrentItem(newItem); newItem->setSelected(true); slotSetupWidget(); nameEdit->setFocus(); nameEdit->selectAll(); applyButton->setEnabled(true); resetButton->setEnabled(true); } // open or close edit mode void StyleManager::slotOk() { static bool isFirst = true; if (m_isEditMode) { disconnect(styleView, SIGNAL(itemSelectionChanged()), this, SLOT(slotSetupWidget())); slotApply(); okButton->setText(QString("%1 >>").arg( tr("&Edit"))); editFrame->hide(); applyButton->hide(); resetButton->hide(); rightFrame->hide(); m_isEditMode = false; for (int i = 0; i < m_items.count(); ++i) { m_items.at(i)->apply(); m_items.at(i)->editMode(false); } okButton->setToolTip( m_enterEditModeOk); slotClean(); slotDocSelectionChanged(); if (!isFirst) move(m_editPosition); m_prefs->set("isEditMode", m_isEditMode); // qDebug() <<"CONNECT slotOK"; // connect(styleView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), // this, SLOT(slotApplyStyle(QTreeWidgetItem*,QTreeWidgetItem*))); // connect(styleView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), // this, SLOT(slotApplyStyle(QTreeWidgetItem*,int))); if (m_isStoryEditMode) { m_isStoryEditMode=false; hide(); } } else { // qDebug() <<"DISCONNECT slotOK"; // disconnect(styleView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), // this, SLOT(slotApplyStyle(QTreeWidgetItem*,QTreeWidgetItem*))); // disconnect(styleView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), // this, SLOT(slotApplyStyle(QTreeWidgetItem*,int))); slotSetupWidget(); m_editPosition.setX(x()); m_editPosition.setY(y()); m_prefs->set("eX", x()); m_prefs->set("eY", y()); editFrame->show(); applyButton->show(); resetButton->show(); rightFrame->show(); m_isEditMode = true; for (int i = 0; i < m_items.count(); ++i) m_items.at(i)->editMode(true); okButton->setToolTip( m_exitEditModeOk); slotClean(); m_prefs->set("isEditMode", m_isEditMode); connect(styleView, SIGNAL(itemSelectionChanged()), this, SLOT(slotSetupWidget())); } setOkButtonText(); isFirst = false; resize(1, 1); // megahack to keep palette small updateGeometry(); adjustSize(); } void StyleManager::addNewType(StyleItem *item, bool loadFromDoc) { if (item) { m_item = item; QList styles = m_item->styles(loadFromDoc); StyleViewItem *rootItem = new StyleViewItem(styleView, m_item->typeName()); styleView->expandItem(rootItem); QMap sitems; for (int i = 0; i < styles.count(); ++i) // set the list of styles of this type { StyleViewItem *sitem; if (styles[i].second.isNull()) { sitem = new StyleViewItem(rootItem, styles[i].first, m_item->typeName()); } else if (sitems.contains(styles[i].second)) { StyleViewItem *parent = sitems[styles[i].second]; sitem = new StyleViewItem(parent, styles[i].first, m_item->typeName()); styleView->expandItem(parent); } else { bool postpone = false; // search if parent is in remaing styles for (int j = i+1; j < styles.count(); ++j) { if (styles[j].first == styles[i].second) { styles.append(styles[i]); // postpone postpone = true; } } if (postpone) continue; else { qDebug() << QString("stylemanager: unknown parent '%1' of %2 style '%3'").arg(styles[i].second).arg(m_item->typeName()).arg(styles[i].first); sitem = new StyleViewItem(rootItem, styles[i].first, m_item->typeName()); } } sitems[styles[i].first] = sitem; QString shortcutValue(m_item->shortcut(sitem->text(NAME_COL))); sitem->setText(SHORTCUT_COL, shortcutValue); QString key = sitem->rootName() + SEPARATOR + sitem->text(NAME_COL); if (m_styleActions.contains(key)) continue; m_styleActions[key] = new ScrAction(ScrAction::DataQString, QPixmap(), QPixmap(), tr("&Apply") , shortcutValue, m_doc->view(), 0, 0.0, key); connect(m_styleActions[key], SIGNAL(triggeredData(QString)), this, SLOT(slotApplyStyle(QString))); } } } void StyleManager::slotDirty() { QTreeWidgetItemIterator it(styleView, QTreeWidgetItemIterator::Selected); while (*it) { StyleViewItem *item = dynamic_cast(*it); if (item) { item->setDirty(true); applyButton->setEnabled(true); resetButton->setEnabled(true); } ++it; } applyButton->setEnabled(true); resetButton->setEnabled(true); } void StyleManager::slotClean() { QTreeWidgetItemIterator it(styleView); while (*it) { StyleViewItem *item = dynamic_cast(*it); if (item) item->setDirty(false); ++it; } if (m_isEditMode) { StyleItem *tmp = m_item; for (int i = 0; i < m_items.count(); ++i) { m_item = m_items.at(i); reloadStyleView(); } slotSetupWidget(); m_item = tmp; } applyButton->setEnabled(false); resetButton->setEnabled(false); uniqueLabel->hide(); } void StyleManager::reloadStyleView(bool loadFromDoc) { QTreeWidgetItemIterator it(styleView, QTreeWidgetItemIterator::Selected); QList > selected; while (*it) { StyleViewItem *item = dynamic_cast(*it); if (item) selected << QPair(item->rootName(), item->text(NAME_COL)); ++it; } styleView->clear(); if (m_item && loadFromDoc) m_item->reload(); for (int i = 0; i < m_items.count(); ++i) addNewType(m_items.at(i), false); QTreeWidgetItemIterator it2(styleView, QTreeWidgetItemIterator::Selectable); while (*it2) { StyleViewItem *item = dynamic_cast(*it2); if (item) { for (int i = 0; i < selected.count(); ++i) { if (selected[i].first == item->rootName() && selected[i].second == item->text(NAME_COL)) { item->setDirty(false); styleView->setCurrentItem(item); item->setSelected(true); break; } } } ++it2; } //#7318 Do not auto resize vertically styleView->resizeColumnToContents(0); // styleView->repaint(); } void StyleManager::insertShortcutPage(QTabWidget *twidget) { if (twidget) { if (!m_shortcutWidget) { m_shortcutWidget = new ShortcutWidget(0); connect(m_shortcutWidget, SIGNAL(newKey(const QString&)), this, SLOT(slotShortcutChanged(const QString&))); } twidget->addTab(m_shortcutWidget, tr("Shortcut")); } } void StyleManager::slotNameChanged(const QString& name) { if (m_item && !nameIsUnique(name)) { uniqueLabel->show(); okButton->setEnabled(false); applyButton->setEnabled(false); return; } else if (uniqueLabel->isVisible()) { uniqueLabel->hide(); okButton->setEnabled(true); applyButton->setEnabled(true); } if (m_item) { m_item->nameChanged(name); updateActionName(styleView->currentItem()->text(NAME_COL), name); styleView->currentItem()->setText(NAME_COL, name); applyButton->setEnabled(true); resetButton->setEnabled(true); } } void StyleManager::updateActionName(const QString &oldName, const QString &newName) { if (!m_item) return; QString oldKey = m_item->typeName() + SEPARATOR + oldName; QString newKey = m_item->typeName() + SEPARATOR + newName; if (m_styleActions.contains(oldKey)) { ScrAction *a = m_styleActions[oldKey]; disconnect(a, SIGNAL(triggeredData(QString)), this, SLOT(slotApplyStyle(QString))); ScrAction *b = new ScrAction(ScrAction::DataQString, QPixmap(), QPixmap(), "", a->shortcut(), m_doc->view(), 0, 0.0, newKey); m_styleActions.remove(oldKey); delete a; m_styleActions[newKey] = b; connect(b, SIGNAL(triggeredData(QString)), this, SLOT(slotApplyStyle(QString))); } } void StyleManager::slotShortcutChanged(const QString& shortcut) { if (!m_doc) return; StyleViewItem *sitem = dynamic_cast(styleView->currentItem()); if (!sitem) return; if (!shortcut.isNull() && shortcutExists(shortcut)) { QMessageBox::information(this, CommonStrings::trWarning, tr("This key sequence is already in use"), CommonStrings::tr_OK); if (m_shortcutWidget) m_shortcutWidget->setShortcut(m_item->shortcut(sitem->text(NAME_COL))); return; } sitem->setText(SHORTCUT_COL, shortcut.isNull() ? "" : shortcut); QString key = sitem->rootName() + SEPARATOR + sitem->text(NAME_COL); if (m_styleActions.contains(key)) m_styleActions[key]->setShortcut(shortcut); else { m_styleActions[key] = new ScrAction(ScrAction::DataQString, QPixmap(), QPixmap(), "", shortcut, m_doc->view(), 0, 0.0, key); connect(m_styleActions[key], SIGNAL(triggeredData(QString)), this, SLOT(slotApplyStyle(QString))); } if (m_item) m_item->setShortcut(shortcut); } bool StyleManager::shortcutExists(const QString &keys) { QKeySequence key(keys); QMap >::iterator it; for (it = m_styleActions.begin(); it != m_styleActions.end(); ++it) { if ((*it)->shortcut() == key) return true; } ApplicationPrefs *prefsData=&(PrefsManager::instance()->appPrefs); for (QMap::Iterator it=prefsData->KeyActions.begin(); it!=prefsData->KeyActions.end(); ++it) { if (key.matches(it.value().keySequence) != QKeySequence::NoMatch) return true; } return false; } void StyleManager::slotApplyStyle(QString keyString) { if (m_isEditMode) return; QStringList slist = keyString.split(SEPARATOR, QString::SkipEmptyParts); Q_ASSERT(slist.count() == 2); loadType(slist[0]); m_item->toSelection(slist[1]); slotDocSelectionChanged(); m_rcStyle = QString::null; m_rcType = QString::null; } bool StyleManager::nameIsUnique(const QString &name) { QList names = m_item->styles(false); for (int i = 0; i < names.count(); ++i) { if (names[i].first == name) return false; } return true; } // setups the selected type and edit widgets related to it void StyleManager::slotSetupWidget() { QPair selection = namesFromSelection(); QString typeName = selection.first; // qDebug()<<"slotSetupWidget"<setEnabled(false); // nothing selected or two or more different types else if (!m_item || m_item->typeName() != typeName || m_widget != m_item->widget()) loadType(typeName); // new type selected else if (m_widget && !m_widget->isEnabled()) m_widget->setEnabled(true); disconnect(nameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(slotNameChanged(const QString&))); if (!typeName.isNull()) { m_item->selected(selection.second); if (selection.second.count() > 1) { nameEdit->setText( tr("More than one style selected")); nameEdit->setEnabled(false); if (m_shortcutWidget) { m_shortcutWidget->setEnabled(false); m_shortcutWidget->setShortcut(QString::null); } } else { nameEdit->setText(selection.second[0]); // qDebug() << selection.second[0] << m_item->isDefaultStyle(selection.second[0]); nameEdit->setEnabled(! (m_item->isDefaultStyle(selection.second[0]))); if (m_shortcutWidget) { m_shortcutWidget->setEnabled(true); m_shortcutWidget->setShortcut(m_item->shortcut(selection.second[0])); } } } else { nameEdit->setText(""); nameEdit->setEnabled(false); } connect(nameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(slotNameChanged(const QString&))); } void StyleManager::slotApplyStyle(QTreeWidgetItem *item) { StyleViewItem *sitem = dynamic_cast(item); if (m_isEditMode || !sitem || sitem->isRoot()) return; // don't apply a style in edit mode or if there was no item/type selected styleView->clearSelection(); if (!m_item || m_item->typeName() != sitem->rootName()) loadType(sitem->rootName()); // load the type where we want to apply this style Q_ASSERT(m_item); m_item->toSelection(sitem->text(NAME_COL)); // apply selected style to the selection slotDocSelectionChanged(); m_rcStyle = QString::null; m_rcType = QString::null; } void StyleManager::slotApplyStyle(QTreeWidgetItem *newitem, QTreeWidgetItem *) { slotApplyStyle(newitem); } void StyleManager::slotApplyStyle(QTreeWidgetItem *item, int) { slotApplyStyle(item); } void StyleManager::slotDocSelectionChanged() { if (m_isEditMode) return; // don't track changes when in edit mode // qDebug() << "Style Manager : doc selection changed"; // qDebug() <<"DISCONNECT slotDocSelectionChanged"; // disconnect(styleView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), // this, SLOT(slotApplyStyle(QTreeWidgetItem*, QTreeWidgetItem*))); styleView->clearSelection(); QList > selected; for (int i = 0; i < m_items.count(); ++i) selected << QPair(m_items.at(i)->typeName(), m_items.at(i)->fromSelection()); QTreeWidgetItemIterator it(styleView, QTreeWidgetItemIterator::Selectable); StyleViewItem *item; while (*it) { item = dynamic_cast(*it); if (item) { for (int i = 0; i < selected.count(); ++i) { if (item->rootName() == selected[i].first && item->text(NAME_COL) == selected[i].second) { styleView->setCurrentItem(item); item->setSelected(true); } } } ++it; } // qDebug() <<"CONNECT slotDocSelectionChanged"; // connect(styleView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), // this, SLOT(slotApplyStyle(QTreeWidgetItem*,QTreeWidgetItem*))); } void StyleManager::slotDocStylesChanged() { qDebug() << "slotDocStylesChanged()"; } // QPair.first == QString::null if nothing is selected or if // there are items from more than one type in the selection // if selection is valid (only from single type) QPair.first will // include the type name and QPair.second will have all the selected // stylenames in it QPair StyleManager::namesFromSelection() { QString typeName(QString::null); QStringList styleNames; if (m_rcStyle.isNull()) { foreach(QTreeWidgetItem * it, styleView->selectedItems()) { StyleViewItem *item = dynamic_cast(it); if (!item) { continue; } else if (typeName.isNull()) typeName = item->rootName(); else if (!typeName.isNull() && typeName != item->rootName()) { typeName = QString::null; break; // two different types selected returning null } if (!item->isRoot()) styleNames << item->text(NAME_COL); } } else // right click selection which doesn't show in the gui { typeName = m_rcType; styleNames << m_rcStyle; } return QPair(typeName, styleNames); } // sets the current type to name including m_item and the main widget // for editing styles void StyleManager::loadType(const QString &name) { m_item = 0; for (int i = 0; i < m_items.count(); ++i) { if (m_items.at(i)->typeNameSingular() == name || m_items.at(i)->typeName() == name) { m_item = m_items.at(i); break; } } if (!m_item) return; if (m_widget) { // remove the old style type's widget m_widget->hide(); m_layout->removeWidget(m_widget); // m_widget->reparent(0,0, QPoint(0,0), false); // show the widget for the new style type if (m_shortcutWidget) m_widget->removeTab(m_widget->indexOf(m_shortcutWidget)); } m_widget = m_item->widget(); // show the widget for the style type //<<#8230: Hide the shortcut page as it does not work //insertShortcutPage(m_widget); //>> m_widget->setParent(mainFrame); m_layout->addWidget(m_widget, 0, 0); layout()->activate(); m_widget->resize(m_widget->minimumSizeHint()); m_widget->show(); } void StyleManager::hideEvent(QHideEvent *e) { if (m_doc) disconnect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(slotDocSelectionChanged())); m_prefs->set("eX", x()); m_prefs->set("eY", y()); m_prefs->set("isEditMode", m_isEditMode); m_prefs->set("InitX", x()); m_prefs->set("InitY", y()); storeVisibility(false); storePosition(); ScrPaletteBase::hideEvent(e); emit closed(); } void StyleManager::closeEvent(QCloseEvent *e) { m_prefs->set("eX", x()); m_prefs->set("eY", y()); m_prefs->set("isEditMode", m_isEditMode); m_prefs->set("InitX", x()); m_prefs->set("InitY", y()); storeVisibility(false); storePosition(); ScrPaletteBase::closeEvent(e); emit closed(); } void StyleManager::showEvent(QShowEvent *e) { static bool isFirst = true; if (isModal()) { m_isStoryEditMode=true; applyButton->setEnabled(false); slotEdit(); } setOkButtonText(); ScrPaletteBase::showEvent(e); if (isFirst) { QPoint p(m_prefs->getInt("InitX", x()), m_prefs->getInt("InitY", y())); move(p); isFirst = false; } if (m_doc) connect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(slotDocSelectionChanged())); } StyleManager::~StyleManager() { m_prefs->set("eX", x()); m_prefs->set("eY", y()); m_prefs->set("isEditMode", m_isEditMode); m_prefs->set("InitX", x()); m_prefs->set("InitY", y()); storeVisibility(this->isVisible()); storePosition(); }