Subversion Repositories Scribus

Rev

Rev 23653 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
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 "pagepalette_masterpages.h"

#include <QApplication>
#include <QCloseEvent>
#include <QCursor>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QListWidget>
#include <QListWidgetItem>
#include <QMessageBox>
#include <QScopedPointer>
#include <QSpacerItem>
#include <QString>
#include <QStringList>
#include <QToolButton>
#include <QToolTip>
#include <QVBoxLayout>

#include "appmodes.h"
#include "canvasmode.h"
#include "commonstrings.h"
#include "iconmanager.h"
#include "mergedoc.h"
#include "newtemp.h"
#include "pagestructs.h"
#include "prefsmanager.h"
#include "scpage.h"
#include "scribus.h"
#include "scribusapp.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "scribusXml.h"
#include "selection.h"
#include "util.h"
#include "util_os.h"


PagePalette_MasterPages::PagePalette_MasterPages( QWidget* parent, ScribusView *pCurrentView, const QString& masterPageName) : QWidget(parent)
{
        m_doc  = pCurrentView->m_doc;
        m_view = pCurrentView;

        setupUi(this);
        iconSetChange();

        masterPageListBox->setSelectionMode(QAbstractItemView::ExtendedSelection);
        styleChange();
        languageChange();

        if (masterPageName.isEmpty())
                m_currentPage = m_doc->MasterNames.begin().key();
        else
                m_currentPage = masterPageName;
        updateMasterPageList(m_currentPage);
        m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);

        setMinimumSize(sizeHint());

        // signals and slots connections
        connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
        connectSignals();
}

void PagePalette_MasterPages::setView(ScribusView* view, const QString& masterPageName)
{
//      ScribusView* oldView = m_view;
//      QString oldPage = m_currentPage;

        disconnectSignals();
        m_view = view;
        m_doc = m_view ? m_view->m_doc : nullptr;

        if (!view)
        {
                this->setEnabled(false);
                return;
        }

        if (masterPageName.isEmpty() && m_doc->masterPageMode())
                m_currentPage = m_doc->currentPage()->pageName();
        else if (masterPageName.isEmpty())
                m_currentPage = m_doc->MasterNames.begin().key();
        else
                m_currentPage = masterPageName;

        QString currentPageName;
        if (m_doc->masterPageMode())
                currentPageName = m_doc->currentPage()->pageName();
        if (m_doc->masterPageMode() && m_currentPage != currentPageName)
                m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);

        this->setEnabled(m_doc->masterPageMode());
        connectSignals();
}

void PagePalette_MasterPages::connectSignals()
{
        connect(duplicateButton, SIGNAL(clicked()), this, SLOT(duplicateMasterPage()));
        connect(deleteButton   , SIGNAL(clicked()), this, SLOT(deleteMasterPage()));
        connect(newButton      , SIGNAL(clicked()), this, SLOT(newMasterPage()));
        connect(importButton   , SIGNAL(clicked()), this, SLOT(importPage()));
        connect(masterPageListBox, SIGNAL(itemClicked(QListWidgetItem*)),
                         this, SLOT(selectMasterPage(QListWidgetItem*)));
        connect(masterPageListBox, SIGNAL(itemChanged(QListWidgetItem*)),
                         this, SLOT(renameMasterPage( QListWidgetItem*)));
        connect(finishButton   , SIGNAL(released()), this, SIGNAL(finished()));
}

void PagePalette_MasterPages::disconnectSignals()
{
        disconnect(duplicateButton, SIGNAL(clicked()), this, SLOT(duplicateMasterPage()));
        disconnect(deleteButton   , SIGNAL(clicked()), this, SLOT(deleteMasterPage()));
        disconnect(newButton      , SIGNAL(clicked()), this, SLOT(newMasterPage()));
        disconnect(importButton   , SIGNAL(clicked()), this, SLOT(importPage()));
        disconnect(masterPageListBox, SIGNAL(itemClicked(QListWidgetItem*)),
                           this, SLOT(selectMasterPage(QListWidgetItem*)));
        disconnect(masterPageListBox, SIGNAL(itemChanged(QListWidgetItem*)),
                           this, SLOT(renameMasterPage( QListWidgetItem*)));
        disconnect(finishButton   , SIGNAL(released()), this, SIGNAL(finished()));
}

void PagePalette_MasterPages::iconSetChange()
{
        IconManager& iconManager = IconManager::instance();

        importButton->setIcon(iconManager.loadIcon("16/document-open.png"));
        newButton->setIcon(iconManager.loadIcon("16/document-new.png"));
        duplicateButton->setIcon(iconManager.loadIcon("16/edit-copy.png"));
        deleteButton->setIcon(iconManager.loadIcon("16/edit-delete.png"));
}

void PagePalette_MasterPages::languageChange()
{
        setWindowTitle( tr( "Edit Master Pages" ) );
        duplicateButton->setToolTip( tr( "Duplicate the selected master page" ) );
        deleteButton->setToolTip( tr( "Delete the selected master page" ) );
        newButton->setToolTip( tr( "Add a new master page" ) );
        importButton->setToolTip( tr( "Import master pages from another document" ) );
}

void PagePalette_MasterPages::styleChange()
{
        PrefsManager& prefsManager = PrefsManager::instance();
        if (prefsManager.appPrefs.uiPrefs.style=="Macintosh" || (os_is_osx() && prefsManager.appPrefs.uiPrefs.style==""))
                finishButton->setMinimumHeight(32);
        else
                finishButton->setMinimumHeight(0);
}

void PagePalette_MasterPages::deleteMasterPage()
{
        bool forceDelete = false;

        // allow to delete multiple pages in one step
        foreach (QListWidgetItem * delItem, masterPageListBox->selectedItems())
        {
                m_currentPage = delItem->text();

                if (isReservedName(m_currentPage))
                        continue;

                QString extraWarn = "";

                if (!forceDelete)
                {
                        for (int i=0; i < m_doc->DocPages.count(); ++i )
                        {
                                if (m_doc->DocPages[i]->masterPageName() == m_currentPage)
                                        extraWarn = tr("This master page is used at least once in the document.");
                        }
                        int exit = ScMessageBox::warning(this,
                                                                                CommonStrings::trWarning,
                                                                                tr("Do you really want to delete master page \"%1\"?").arg(m_currentPage)+"\n"+extraWarn,
                                                                                QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::Cancel,
                                                                                QMessageBox::NoButton// GUI default
                                                                                QMessageBox::YesToAll); // batch default

                        if (exit == QMessageBox::YesToAll)
                                forceDelete = true;
                        if (exit == QMessageBox::No)
                                continue;
                        if (exit == QMessageBox::Cancel)
                                break;
                }

                if (m_doc->appMode == modeEditClip)
                        m_view->requestMode(submodeEndNodeEdit);
                m_doc->scMW()->deletePage2(m_doc->MasterNames[m_currentPage]);
                //<<CB TODO Move back into ScribusDoc::deleteMasterPage();
                //This must happen after the pages have been reformed (view/doc)
                m_doc->rebuildMasterNames();
                // Fix up any pages that refer to the deleted master page
                m_doc->replaceMasterPage(m_currentPage);
        }

        // set the 1st MP for the other slots
        QMap<QString,int>::Iterator it = m_doc->MasterNames.begin();
        m_currentPage = it.key();
        updateMasterPageList(m_currentPage);
        selectMasterPage(m_currentPage);
}

void PagePalette_MasterPages::duplicateMasterPage()
{
        QString name = getUniqueName(m_currentPage, m_doc->MasterNames);
        QScopedPointer<NewTm> dia(new NewTm(this, tr("&Name:"), tr("New Master Page"), m_doc, name));
        if (!dia->exec())
                return;

        if (m_doc->appMode == modeEditClip)
                m_view->requestMode(submodeEndNodeEdit);

        name = dia->Answer->text();

        if (name.isEmpty())
                return;

        name = getNonReservedName(name);
        name = getUniqueName(name, m_doc->MasterNames);

//      PrefsManager& prefsManager = PrefsManager::instance();
        int inde = m_doc->MasterNames[m_currentPage];
        int nr = m_doc->Pages->count();
        ScPage* from = m_doc->Pages->at(inde);
        ScPage* destination = m_doc->addMasterPage(nr, name);
        if (m_doc->pagePositioning() != singlePage)
        {
                int lp = dia->Links->currentIndex();
                if (lp == 0)
                        lp = 1;
                else if (lp == static_cast<int>(dia->Links->count()-1))
                        lp = 0;
                else
                        lp++;
                destination->LeftPg = lp;
        }
        destination->initialMargins.setTop(from->initialMargins.top());
        destination->initialMargins.setBottom(from->initialMargins.bottom());
        if (m_doc->pageSets()[m_doc->pagePositioning()].Columns == 1)
        {
                destination->initialMargins.setLeft(from->initialMargins.left());
                destination->initialMargins.setRight(from->initialMargins.right());
        }
        else
        {
                if (destination->LeftPg != from->LeftPg)
                {
                        if (destination->LeftPg > 1)
                        {
                                destination->initialMargins.setRight(from->initialMargins.left());
                                destination->initialMargins.setLeft(from->initialMargins.left());
                        }
                        else
                        {
                                destination->initialMargins.setLeft(from->initialMargins.left());
                                destination->initialMargins.setRight(from->initialMargins.right());
                        }
                }
                else
                {
                        destination->initialMargins.setLeft(from->initialMargins.left());
                        destination->initialMargins.setRight(from->initialMargins.right());
                }
        }
        //#8321 : incorrect selection of master page on new mp creation/duplication
        //m_doc->setCurrentPage(destination);
        updateMasterPageList(name);
        selectMasterPage(name);
        uint oldItems = m_doc->Items->count();
        uint end2 = m_doc->MasterItems.count();
        int GrMax = m_doc->GroupCounter;
        m_doc->m_Selection->clear();
        if (oldItems>0)
        {
                ScLayers::iterator it;
                m_doc->m_Selection->delaySignalsOn();
                for (it = m_doc->Layers.begin(); it != m_doc->Layers.end(); ++it)
                {
                        for (uint ite = 0; ite < oldItems; ++ite)
                        {
                                PageItem *itemToCopy = m_doc->Items->at(ite);
                                if (itemToCopy->OwnPage == inde && (it->ID == itemToCopy->m_layerID))
                                        m_doc->m_Selection->addItem(itemToCopy, true);
                        }
                        if (m_doc->m_Selection->count() != 0)
                        {
                                ScriXmlDoc ss;
                                QString buffer = ss.writeElem(m_doc, m_doc->m_Selection);
                                ss.readElemToLayer(buffer, m_doc, destination->xOffset(), destination->yOffset(), false, true, it->ID);
                                m_doc->m_Selection->clear();
                        }
                }
                m_doc->m_Selection->clear();
                m_doc->m_Selection->delaySignalsOff();
        }
        uint end3 = m_doc->MasterItems.count();
        for (uint a = end2; a < end3; ++a)
        {
                PageItem *newItem = m_doc->MasterItems.at(a);
                int masterPageIndex = m_doc->MasterNames[name];
                newItem->setMasterPage(masterPageIndex, name);
        }
        from->guides.copy(&destination->guides);
        m_doc->GroupCounter = GrMax + 1;
        m_view->deselectItems(true);
        m_doc->setLoading(false);
        m_view->reformPages();
        m_view->DrawNew();
}

void PagePalette_MasterPages::newMasterPage()
{
        int nr = m_doc->Pages->count();

        QScopedPointer<NewTm> dia(new NewTm(this, tr("Name:"), tr("New MasterPage"), m_doc, tr("New Master Page %1").arg(nr)));
        if (!dia->exec())
                return;

        if (m_doc->appMode == modeEditClip)
                m_view->requestMode(submodeEndNodeEdit);

        auto name = dia->Answer->text();

        if (name.isEmpty())
                return;

        name = getNonReservedName(name);
        name = getUniqueName(name, m_doc->MasterNames);

        m_doc->setCurrentPage(m_doc->addMasterPage(nr, name));
        if (m_doc->pagePositioning() != singlePage)
        {
                int lp = dia->Links->currentIndex();
                if (lp == 0)
                        lp = 1;
                else if (lp == static_cast<int>(dia->Links->count()-1))
                        lp = 0;
                else
                        lp++;
                m_doc->Pages->at(nr)->LeftPg = lp;
        }
        updateMasterPageList(name);
        //#8321 : incorrect selection of master page on new mp creation/duplictation
        //m_view->showMasterPage(m_doc->MasterNames[name]);
        selectMasterPage(name);
        m_view->reformPages();
}

void PagePalette_MasterPages::importPage()
{
        QScopedPointer<MergeDoc> dia(new MergeDoc(this, true));
        if (!dia->exec())
                return;

        if (m_doc->appMode == modeEditClip)
                m_view->requestMode(submodeEndNodeEdit);

        qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
        int nr = m_doc->Pages->count();

        auto indexes = dia->getMasterPageIndexes();
        QString lastName;
        for (auto name: dia->getMasterPageNames())
        {
                name = getUniqueName(name, m_doc->MasterNames);
                m_doc->setCurrentPage(m_doc->addMasterPage(nr, name));

                nr++;
                qApp->processEvents();

                //CB TODO: If we are loading to a new name, we rely on doc->onpage in
                //FileLoader::PasteItem as this call doesn't pass in the new destination page
                m_doc->scMW()->loadPage(dia->getFromDoc(), indexes.first(), true, name);
                qApp->processEvents();

                indexes.removeFirst();
                lastName = name;
        }

        updateMasterPageList(lastName);
        m_view->showMasterPage(m_doc->MasterNames[lastName]);
        qApp->restoreOverrideCursor();
}

void PagePalette_MasterPages::selectMasterPage(QListWidgetItem *item)
{
        m_currentPage = item->data(Qt::UserRole).toString();

        bool deleteEnabled = true;
        deleteEnabled &= (m_doc->MasterNames.count() > 1);
        deleteEnabled &= (m_currentPage != CommonStrings::masterPageNormal);
        deleteEnabled &= (m_currentPage != CommonStrings::trMasterPageNormal);
        deleteButton->setEnabled(deleteEnabled);

        if (m_doc->appMode == modeEditClip)
                m_view->requestMode(submodeEndNodeEdit);
        else if (m_doc->appMode == modeEdit || m_doc->appMode == modeEditGradientVectors)
                m_view->requestMode(modeNormal);
        m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);

        this->setEnabled(true);
}

void PagePalette_MasterPages::selectMasterPage(const QString& name)
{
        if (!m_doc || !m_view)
                return;

        m_currentPage.clear();
        for (int i = 0; i < masterPageListBox->count(); ++i)
        {
                QListWidgetItem* item = masterPageListBox->item(i);
                QString realPageName  = item->data(Qt::UserRole).toString();
                if (item->text() == name)
                {
                        m_currentPage = realPageName;
                        break;
                }
                if (realPageName == name)
                {
                        m_currentPage = name;
                        break;
                }
        }
       
        if (m_currentPage.isEmpty())
                m_currentPage = m_doc->MasterPages.at(0)->pageName();

        bool deleteEnabled = true;
        deleteEnabled &= (m_doc->MasterNames.count() > 1);
        deleteEnabled &= (m_currentPage != CommonStrings::masterPageNormal);
        deleteEnabled &= (m_currentPage != CommonStrings::trMasterPageNormal);
        deleteButton->setEnabled(deleteEnabled);

        if (m_doc->appMode == modeEditClip)
                m_view->requestMode(submodeEndNodeEdit);
        m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);

        this->setEnabled(true);
}

void PagePalette_MasterPages::updateMasterPageList()
{
        QString masterPageName = (m_doc->MasterNames.contains(m_currentPage)) ? m_currentPage : CommonStrings::masterPageNormal;
        updateMasterPageList(masterPageName);
}

void PagePalette_MasterPages::updateMasterPageList(QString masterPageName)
{
        if (!m_doc || !m_view)
                return;

        masterPageListBox->clear();
        for (QMap<QString,int>::Iterator it = m_doc->MasterNames.begin(); it != m_doc->MasterNames.end(); ++it)
        {
                QString mpName = it.key();

                if (it.key() == CommonStrings::masterPageNormal)
                        mpName = CommonStrings::trMasterPageNormal;
                QListWidgetItem* mpItem = new QListWidgetItem(mpName);

                if (!isReservedName(mpName))
                        mpItem->setFlags(mpItem->flags() |= Qt::ItemIsEditable);
                else
                        mpItem->setFlags(mpItem->flags() &= ~Qt::ItemIsEditable);

                mpItem->setData(Qt::UserRole, it.key());
                masterPageListBox->addItem(mpItem);
        }
        deleteButton->setEnabled(m_doc->MasterNames.count() != 1);
        if (masterPageName == CommonStrings::masterPageNormal)
        {
                masterPageName = CommonStrings::trMasterPageNormal;
                deleteButton->setEnabled(false);
        }
        QList<QListWidgetItem *> itL = masterPageListBox->findItems(masterPageName, Qt::MatchExactly);
        if (itL.count() != 0)
                itL.at(0)->setSelected(true);
}

void PagePalette_MasterPages::renameMasterPage(QListWidgetItem * item)
{
        QString oldName(item->data(Qt::UserRole).toString());
        QString newName(item->text());

        if (oldName == newName)
                return;

        // FIXME: the checks in the old version of this function
        // and the ones in m_doc->renameMasterPage() did not match.
        // we should move all MasterPage related code to a new masterpage.h
        // file and remove code from scribusdoc.cpp and from here.
        // at the end, the code below should be:
        //
        // if (m_doc->m_masterPage->rename(oldName, newName))
        // {
        //              bool sigBlocked = masterPageListBox->blockSignals(true);
        //              item->setData(Qt::UserRole, newName);
        //              masterPageListBox->blockSignals(sigBlocked);
        //              updateMasterPageList(newName);
        // }
        // else
        // {
        //              bool sigBlocked = masterPageListBox->blockSignals(true);
        //              item->setText(getTranslatedReservedName(oldName));
        //              masterPageListBox->blockSignals(sigBlocked);
        // }

        if (newName.isEmpty() || isReservedName(newName) ||
                !m_doc->MasterNames.contains(oldName) ||
                m_doc->MasterNames.contains(newName))
        {
                bool sigBlocked = masterPageListBox->blockSignals(true);
                item->setText(oldName);
                masterPageListBox->blockSignals(sigBlocked);
        }
        else
        {
                bool sigBlocked = masterPageListBox->blockSignals(true);
                m_doc->renameMasterPage(oldName, newName);
                item->setData(Qt::UserRole, newName);
                masterPageListBox->blockSignals(sigBlocked);
                updateMasterPageList(newName);
        }
}


void PagePalette_MasterPages::changeEvent(QEvent *e)
{
        if (e->type() == QEvent::LanguageChange)
        {
                languageChange();
                return;
        }
        if (e->type() == QEvent::StyleChange)
        {
                styleChange();
                return;
        }

        QWidget::changeEvent(e);
}

// FIXME: move to a new masterpages.h
bool PagePalette_MasterPages::isReservedName(const QString& name) const
{
        bool retval = name == CommonStrings::masterPageNormal ||
                name == CommonStrings::trMasterPageNormal ||
                name == CommonStrings::masterPageNormalLeft ||
                name == CommonStrings::trMasterPageNormalLeft ||
                name == CommonStrings::masterPageNormalMiddle ||
                name == CommonStrings::trMasterPageNormalMiddle ||
                name == CommonStrings::masterPageNormalRight ||
                name == CommonStrings::trMasterPageNormalRight;
        return retval;
}

// FIXME: move to a new masterpages.h
QString PagePalette_MasterPages::getNonReservedName(const QString& name) const
{
        const QStringList reservedNames = {
                CommonStrings::masterPageNormal,
                CommonStrings::trMasterPageNormal,
                CommonStrings::trMasterPageNormalLeft,
                CommonStrings::trMasterPageNormalMiddle,
                CommonStrings::trMasterPageNormalRight
        };
        return getUniqueName(name, reservedNames);
}

// FIXME: move to a new masterpages.h
QString PagePalette_MasterPages::getTranslatedReservedName(const QString& name) const
{
        if (name == CommonStrings::masterPageNormal)
                return CommonStrings::trMasterPageNormal;
        if (name == CommonStrings::masterPageNormalLeft)
                return CommonStrings::trMasterPageNormalLeft;
        if (name == CommonStrings::masterPageNormalMiddle)
                return CommonStrings::trMasterPageNormalMiddle;
        if (name == CommonStrings::masterPageNormalRight)
                return CommonStrings::trMasterPageNormalRight;
        return name;
}