Back to index

scribus-ng  1.3.4.dfsg+svn20071115
undogui.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008  *   Copyright (C) 2005 by Riku Leino                                      *
00009  *   tsoots@gmail.com                                                      *
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  *   This program is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00019  *   GNU General Public License for more details.                          *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU General Public License     *
00022  *   along with this program; if not, write to the                         *
00023  *   Free Software Foundation, Inc.,                                       *
00024  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00025  ***************************************************************************/
00026 
00027 #include <qlayout.h>
00028 #include <qpixmap.h>
00029 #include <qpushbutton.h>
00030 #include <qrect.h>
00031 #include <qstyle.h>
00032 #include <qtooltip.h>
00033 #include <qcheckbox.h>
00034 #include <qfont.h>
00035 #include <qfontmetrics.h>
00036  
00037 #include "undogui.h"
00038 #include "undogui.moc"
00039 #include "prefsmanager.h"
00040 #include "prefsfile.h"
00041 #include "prefscontext.h"
00042 #include "scribuscore.h"
00043 #include "menumanager.h"
00044 #include "scraction.h"
00045 
00046 extern QPixmap loadIcon(QString nam);
00047 
00048 
00049 UndoGui::UndoGui(QWidget* parent, const char* name, WFlags f) : ScrPaletteBase(parent, name, f)
00050 {
00051 
00052 }
00053 
00054 /*** UndoWidget ***************************************************************/
00055 
00056 UndoWidget::UndoWidget(QWidget* parent, const char* name)
00057 : UndoGui(parent, name)
00058 {
00059        /* BnF standard toolbar buttons
00060        QHBoxLayout* layout = new QHBoxLayout(this, 0, 0, "layout");
00061 
00062 
00063        undoButton = new QToolButton(this, "undoButton");
00064        undoButton->setIconSet(loadIcon("u_undo.png"));
00065        undoButton->setUsesTextLabel(false);
00066        QToolTip::add(undoButton, tr("Undo"));
00067        layout->addWidget(undoButton);
00068        undoMenu = new QPopupMenu(undoButton, "undoMenu");
00069        undoButton->setPopup(undoMenu);
00070        undoButton->setPopupDelay(0);
00071        undoButton->setAutoRaise(true);
00072 
00073        redoButton = new QToolButton(this, "redoButton");
00074        redoButton->setIconSet(loadIcon("u_redo.png"));
00075        redoButton->setUsesTextLabel(false);
00076        QToolTip::add(redoButton, tr("Redo"));
00077        layout->addWidget(redoButton);
00078        redoMenu = new QPopupMenu(redoButton, "redoMenu");
00079        redoButton->setPopup(redoMenu);
00080        redoButton->setPopupDelay(0);
00081        redoButton->setAutoRaise(true);
00082        */
00083        //Scribus action based toolbar button construction
00084        ScCore->primaryMainWindow()->scrActions["editUndoAction"]->addTo(parent);
00085        ScCore->primaryMainWindow()->scrActions["editRedoAction"]->addTo(parent);
00086        ScCore->primaryMainWindow()->scrMenuMgr->createMenu("undoButtonMenu", "undoButtonMenu");
00087        ScCore->primaryMainWindow()->scrMenuMgr->createMenu("redoButtonMenu", "redoButtonMenu");
00088        undoMenu=ScCore->primaryMainWindow()->scrMenuMgr->getLocalPopupMenu("undoButtonMenu");
00089        redoMenu=ScCore->primaryMainWindow()->scrMenuMgr->getLocalPopupMenu("redoButtonMenu");
00090        ScCore->primaryMainWindow()->scrMenuMgr->addMenuToWidgetOfAction("undoButtonMenu", ScCore->primaryMainWindow()->scrActions["editUndoAction"]);
00091        ScCore->primaryMainWindow()->scrMenuMgr->addMenuToWidgetOfAction("redoButtonMenu", ScCore->primaryMainWindow()->scrActions["editRedoAction"]);
00092        QToolButton *undoButton = dynamic_cast<QToolButton*>(ScCore->primaryMainWindow()->scrActions["editUndoAction"]->getWidgetAddedTo());
00093        QToolButton *redoButton = dynamic_cast<QToolButton*>(ScCore->primaryMainWindow()->scrActions["editRedoAction"]->getWidgetAddedTo());
00094        if (undoButton && redoButton)
00095        {
00096               undoButton->setPopupDelay(0);
00097               redoButton->setPopupDelay(0);
00098        }
00099        
00100        ScCore->primaryMainWindow()->scrActions["editCut"]->addTo(parent);
00101        ScCore->primaryMainWindow()->scrActions["editCopy"]->addTo(parent);
00102        ScCore->primaryMainWindow()->scrActions["editPaste"]->addTo(parent);
00103        ScCore->primaryMainWindow()->scrMenuMgr->addMenuToWidgetOfAction("EditPasteRecent", ScCore->primaryMainWindow()->scrActions["editPaste"]);
00104        
00105        /* BnF Undo buttons
00106        connect(undoButton, SIGNAL(clicked()), this, SLOT(undoClicked()));
00107        connect(redoButton, SIGNAL(clicked()), this, SLOT(redoClicked()));
00108        */
00109        connect(undoMenu, SIGNAL(activated(int)), this, SLOT(undoMenuClicked(int)));
00110        connect(redoMenu, SIGNAL(activated(int)), this, SLOT(redoMenuClicked(int)));
00111 }
00112 
00113 void UndoWidget::clear()
00114 {
00115        undoMenu->clear();
00116        undoItems.clear();
00117        //Scribus disable
00118        ScCore->primaryMainWindow()->scrActions["editUndoAction"]->setEnabled(false);
00119        // BnF disable
00120        //undoButton->setEnabled(false);
00121        redoMenu->clear();
00122        redoItems.clear();
00123        //Scribus disable;
00124        ScCore->primaryMainWindow()->scrActions["editRedoAction"]->setEnabled(false);
00125        // BnF disable
00126        //redoButton->setEnabled(false);
00127 }
00128 
00129 void UndoWidget::undoClicked()
00130 {
00131        if (undoItems.size() > 0)
00132               emit undo(1);
00133 }
00134 
00135 void UndoWidget::redoClicked()
00136 {
00137        if (redoItems.size() > 0)
00138               emit redo(1);
00139 }
00140 
00141 void UndoWidget::undoMenuClicked(int id)
00142 {
00143        int steps = undoMenu->indexOf(id) + 1;
00144        emit undo(steps);
00145 }
00146 
00147 void UndoWidget::redoMenuClicked(int id)
00148 {
00149        int steps = redoMenu->indexOf(id) + 1;
00150        emit redo(steps);
00151 }
00152 
00153 void UndoWidget::insertUndoItem(UndoObject* target, UndoState* state)
00154 {
00155        undoItems.insert(undoItems.begin(), QString( tr("%1: %2", "undo target: action (f.e. Text frame: Resize)"))
00156                                         .arg(target->getUName()).arg(state->getName()));
00157        clearRedo();
00158        updateUndoMenu();
00159        updateRedoMenu();
00160 }
00161 
00162 void UndoWidget::insertRedoItem(UndoObject* target, UndoState* state)
00163 {
00164        redoItems.push_back(QString( tr("%1: %2", "undo target: action (f.e. Text frame: Resize)"))
00165                         .arg(target->getUName()).arg(state->getName()));
00166        updateRedoMenu();
00167        updateUndoMenu();
00168 }
00169 
00170 void UndoWidget::clearRedo()
00171 {
00172        redoItems.erase(redoItems.begin(), redoItems.end());
00173        updateRedoMenu();
00174 }
00175 
00176 void UndoWidget::updateUndoMenu()
00177 {
00178        undoMenu->clear();
00179        for (uint i = 0; i < MENU_HEIGHT && i < undoItems.size(); ++i)
00180               undoMenu->insertItem(undoItems[i]);
00181        //BnF
00182        //undoButton->setEnabled(undoMenu->count() != 0);
00183        //SCribus
00184        //ScMW->scrActions["editUndoAction"]->setEnabled(undoMenu->count() != 0);
00185        updateUndoActions();
00186 }
00187 
00188 void UndoWidget::updateRedoMenu()
00189 {
00190        redoMenu->clear();
00191        for (uint i = 0; i < MENU_HEIGHT && i < redoItems.size(); ++i)
00192               redoMenu->insertItem(redoItems[i]);
00193        //BnF
00194        //redoButton->setEnabled(redoMenu->count() != 0);
00195        //Scribus
00196        //ScMW->scrActions["editRedoAction"]->setEnabled(redoMenu->count() != 0);
00197        updateUndoActions();
00198 }
00199 
00200 void UndoWidget::updateUndoActions()
00201 {
00202        ScCore->primaryMainWindow()->scrActions["editUndoAction"]->setEnabled(undoMenu->count() != 0);
00203        ScCore->primaryMainWindow()->scrActions["editRedoAction"]->setEnabled(redoMenu->count() != 0);
00204 }
00205 
00206 void UndoWidget::updateUndo(int steps)
00207 {
00208        for (int i = 0; i < steps; ++i)
00209        {
00210               redoItems.insert(redoItems.begin(), undoItems[0]);
00211               undoItems.erase(undoItems.begin());       
00212        }
00213        updateUndoMenu();
00214        updateRedoMenu();
00215 }
00216 
00217 void UndoWidget::updateRedo(int steps)
00218 {
00219        for (int i = 0; i < steps; ++i)
00220        {
00221               undoItems.insert(undoItems.begin(), redoItems[0]);
00222               redoItems.erase(redoItems.begin());       
00223        }
00224        updateUndoMenu();
00225        updateRedoMenu();
00226 }
00227 
00228 void UndoWidget::popBack()
00229 {
00230        if (undoItems.size() > 0)
00231        {
00232               undoItems.erase(undoItems.end() - 1);
00233               updateUndoMenu();
00234        }
00235 }
00236 
00237 UndoWidget::~UndoWidget()
00238 {
00239        
00240 }
00241 
00242 /*** UndoPalette **************************************************************/
00243 
00244 UndoPalette::UndoPalette(QWidget* parent, const char* name)
00245 : UndoGui(parent, name)
00246 {
00247        currentSelection = 0;
00248        redoItems = 0;
00249        QVBoxLayout* layout = new QVBoxLayout(this, 5, 5, "layout");
00250 
00251        objectBox = new QCheckBox(this, "objectBox");
00252        layout->addWidget(objectBox);
00253 //     objectBox->setEnabled(false);
00254 
00255        undoList = new QListBox(this, "undoList");
00256        undoList->setMultiSelection(false);
00257        undoList->setSelectionMode(QListBox::Single);
00258        layout->addWidget(undoList);
00259        
00260        QHBoxLayout* buttonLayout = new QHBoxLayout(0, 0, 5, "buttonLayout"); 
00261        undoButton = new QPushButton(loadIcon("16/edit-undo.png"), "", this, "undoButton");
00262        buttonLayout->addWidget(undoButton);
00263        redoButton = new QPushButton(loadIcon("16/edit-redo.png"), "", this, "redoButton");
00264        buttonLayout->addWidget(redoButton);
00265        //Save the translated key sequence - hopefully we get the translated one here!
00266        initialUndoKS = undoButton->accel();
00267        initialRedoKS = redoButton->accel();
00268        layout->addLayout(buttonLayout);
00269 
00270        updateFromPrefs();
00271        languageChange();
00272        connect(PrefsManager::instance(), SIGNAL(prefsChanged()), this, SLOT(updateFromPrefs()));
00273        connect(undoButton, SIGNAL(clicked()), this, SLOT(undoClicked()));
00274        connect(redoButton, SIGNAL(clicked()), this, SLOT(redoClicked()));
00275        connect(undoList, SIGNAL(highlighted(int)), this, SLOT(undoListClicked(int)));
00276        connect(undoList, SIGNAL(onItem(QListBoxItem*)), this, SLOT(showToolTip(QListBoxItem*)));
00277        connect(undoList, SIGNAL(onViewport()), this, SLOT(removeToolTip()));
00278        connect(objectBox, SIGNAL(toggled(bool)), this, SLOT(objectCheckBoxClicked(bool)));
00279        connect(ScCore->primaryMainWindow()->scrActions["editActionMode"], SIGNAL(toggled(bool)),
00280                objectBox, SLOT(setChecked(bool)));
00281        connect(objectBox, SIGNAL(toggled(bool)), 
00282                      ScCore->primaryMainWindow()->scrActions["editActionMode"], SLOT(setOn(bool)));
00283 }
00284 
00285 void UndoPalette::clear()
00286 {
00287        undoList->clear();
00288        undoList->insertItem( tr("Initial State"));
00289        undoButton->setEnabled(false);
00290        redoButton->setEnabled(false);
00291 }
00292 
00293 void UndoPalette::updateFromPrefs()
00294 {
00295        undoButton->setAccel(ScCore->primaryMainWindow()->scrActions["editUndoAction"]->accel());
00296        redoButton->setAccel(ScCore->primaryMainWindow()->scrActions["editRedoAction"]->accel());
00297 }
00298 
00299 void UndoPalette::languageChange()
00300 {
00301        setCaption( tr("Action History")); 
00302        objectBox->setText( tr("Show selected object only"));
00303        undoButton->setText( tr("&Undo"));
00304        redoButton->setText( tr("&Redo"));
00305 }
00306 
00307 void UndoPalette::insertUndoItem(UndoObject* target, UndoState* state)
00308 {
00309        clearRedo();
00310        undoList->insertItem(new UndoItem(target->getUName(), state->getName(),
00311                          state->getDescription(), target->getUPixmap(),
00312                          state->getPixmap(), true));
00313        currentSelection = undoList->numRows() - 1;
00314        updateList();
00315 }
00316 
00317 void UndoPalette::insertRedoItem(UndoObject* target, UndoState* state)
00318 {
00319        if (undoList->count() == 1)
00320        {
00321               undoList->setSelected(0, true);
00322               currentSelection = 0;
00323        }
00324        undoList->insertItem(new UndoItem(target->getUName(), state->getName(),
00325                          state->getDescription(), target->getUPixmap(),
00326                          state->getPixmap(), false));
00327        updateList();
00328 }
00329 
00330 void UndoPalette::updateUndo(int steps)
00331 {
00332        if (undoList->currentItem() == currentSelection)
00333        {
00334               currentSelection -= steps;
00335               updateList();
00336        }
00337 }
00338 
00339 void UndoPalette::updateRedo(int steps)
00340 {
00341        if (undoList->currentItem() == currentSelection)
00342        {
00343               currentSelection += steps;
00344               updateList();
00345        }
00346 }
00347 
00348 void UndoPalette::popBack()
00349 {
00350        if (undoList->count() > 1)
00351        {
00352               undoList->removeItem(0);
00353               currentSelection = undoList->numRows() - 1;
00354        }
00355 }
00356 
00357 void UndoPalette::updateList()
00358 {
00359        undoList->setCurrentItem(currentSelection);
00360        undoList->setSelected(currentSelection, true);
00361        redoButton->setEnabled(currentSelection < undoList->numRows() - 1);
00362        undoButton->setEnabled(currentSelection > 0);
00363        if (!undoList->itemVisible(currentSelection))
00364               undoList->setBottomItem(currentSelection);
00365        for (int i = 0; i < undoList->numRows(); ++i)
00366        {
00367               UndoItem *item = dynamic_cast<UndoItem*>(undoList->item(i));
00368               if (!item)
00369                      continue;
00370 
00371               item->setUndoAction(currentSelection >= i);
00372        }
00373 }
00374 
00375 void UndoPalette::updateUndoActions()
00376 {
00377        //ScMW->scrActions["editUndoAction"]->setEnabled(currentSelection > 0);
00378        //ScMW->scrActions["editRedoAction"]->setEnabled(currentSelection < undoList->numRows() - 1);
00379 }
00380 
00381 void UndoPalette::clearRedo()
00382 {
00383        for (int i = (undoList->numRows() - 1); i > currentSelection; --i)
00384               undoList->removeItem(i);
00385 }
00386 
00387 void UndoPalette::undoClicked()
00388 {
00389        emit undo(1);
00390 }
00391 
00392 void UndoPalette::redoClicked()
00393 {
00394        emit redo(1);
00395 }
00396 
00397 void UndoPalette::undoListClicked(int i)
00398 {
00399        if (i == currentSelection || (i == 0 && undoList->count() == 1))
00400               return;
00401        if (i > currentSelection)
00402               emit redo(i - currentSelection);
00403        else if (i < currentSelection)
00404               emit undo(currentSelection - i);
00405        currentSelection = i;
00406        updateList();
00407 }
00408 
00409 void UndoPalette::objectCheckBoxClicked(bool on)
00410 {
00411        emit objectMode(on);
00412 }
00413 
00414 void UndoPalette::showToolTip(QListBoxItem *i)
00415 {
00416        UndoItem *item = dynamic_cast<UndoItem*>(i);
00417        if (item)
00418        {
00419               QString tip = item->getDescription();
00420               if (tip != 0)
00421                 QToolTip::add(undoList, tip);
00422        }
00423        else
00424               removeToolTip();
00425 }
00426 
00427 void UndoPalette::removeToolTip()
00428 {
00429        QToolTip::remove(undoList);
00430 }
00431 
00432 UndoPalette::~UndoPalette()
00433 {
00434        
00435 }
00436 
00437 /*** UndoPalette::UndoItem ****************************************************/
00438 
00439 UndoPalette::UndoItem::UndoItem() : QListBoxItem()
00440 {
00441        target = "";
00442        action = "";
00443        description = "";
00444        targetpixmap = NULL;
00445        actionpixmap = NULL;
00446        isUndoAction_ = true;
00447 }
00448 
00449 UndoPalette::UndoItem::UndoItem(const UndoItem &another) : QListBoxItem()
00450 {
00451        target = another.target;
00452        action = another.action;
00453        description = another.description;
00454        targetpixmap = another.targetpixmap;
00455        actionpixmap = another.actionpixmap;
00456        isUndoAction_ = another.isUndoAction_;
00457 }
00458 
00459 UndoPalette::UndoItem::UndoItem(const QString &targetName,
00460                                 const QString &actionName,
00461                                 const QString &actionDescription,
00462                                 QPixmap *targetPixmap,
00463                                 QPixmap *actionPixmap,
00464                                 bool isUndoAction)
00465 : QListBoxItem(),
00466 targetpixmap(targetPixmap),
00467 actionpixmap(actionPixmap),
00468 target(targetName),
00469 action(actionName),
00470 description(actionDescription),
00471 isUndoAction_(isUndoAction)
00472 {
00473 
00474 }
00475 
00476 void UndoPalette::UndoItem::paint(QPainter *painter)
00477 {
00478        if (targetpixmap)
00479               painter->drawPixmap(5, 5, *targetpixmap);
00480        if (actionpixmap)
00481               painter->drawPixmap(5, 5, *actionpixmap);
00482        QPen  p = QPen(painter->pen());
00483        QFont f = QFont(painter->font());
00484        painter->setFont(f);
00485        if (isUndoAction_)
00486        {
00487               p.setColor(QColor("black"));
00488               f.setItalic(false);
00489        }
00490        else
00491        {
00492               p.setColor(QColor("darkGray"));
00493               f.setItalic(true);
00494        }
00495        painter->setPen(p);
00496        painter->setFont(f);
00497        painter->drawText(32, QFontMetrics(f).height(), target);
00498        painter->drawText(32, (2 * QFontMetrics(painter->font()).height()), action);
00499 }
00500 
00501 int UndoPalette::UndoItem::height(const QListBox *lb) const
00502 {
00503        if (lb)
00504        {
00505               int fontHeight = 2 * QFontMetrics(lb->font()).lineSpacing() + 2;
00506               if (actionpixmap)
00507                      return fontHeight > (10 + actionpixmap->height()) ?
00508                    fontHeight : (10 + actionpixmap->height());
00509               else if (targetpixmap)
00510                      return fontHeight > (10 + targetpixmap->height()) ?
00511                    fontHeight : (10 + targetpixmap->height());
00512               else
00513                      return fontHeight;
00514        }
00515        else
00516               return 0;
00517 }
00518 
00519 int UndoPalette::UndoItem::width(const QListBox *lb) const
00520 {
00521        if (lb)
00522               return target.length() > action.length() ?
00523                39 + QFontMetrics(lb->font()).width(target) :
00524                39 + QFontMetrics(lb->font()).width(action);
00525        else
00526               return 0;
00527 }
00528 
00529 QString UndoPalette::UndoItem::getDescription()
00530 {
00531   return description;
00532 }
00533 
00534 bool UndoPalette::UndoItem::isUndoAction()
00535 {
00536        return isUndoAction_;
00537 }
00538 
00539 void UndoPalette::UndoItem::setUndoAction(bool isUndo)
00540 {
00541        isUndoAction_ = isUndo;
00542 }
00543 
00544 UndoPalette::UndoItem::~UndoItem()
00545 {
00546 
00547 }