Index: trunk/kdeextragear-1/gwenview/src/gwenviewui.rc =================================================================== --- trunk/kdeextragear-1/gwenview/src/gwenviewui.rc (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gwenviewui.rc (revision 263335) @@ -1,96 +1,98 @@ - + &View + &Window Main Toolbar + Location Toolbar Index: trunk/kdeextragear-1/gwenview/src/gvmainwindow.h =================================================================== --- trunk/kdeextragear-1/gwenview/src/gvmainwindow.h (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gvmainwindow.h (revision 263335) @@ -1,190 +1,191 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab /* Gwenview - A simple image viewer for KDE Copyright (c) 2000-2003 Aurélien Gâteau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef MAINWINDOW_H #define MAINWINDOW_H // Qt #include // KDE #include #include class QLabel; class KAction; class KHistoryCombo; class KToggleAction; class KToolBar; class KToolBarPopupAction; class KURLCompletion; class GVDirView; class GVFileViewStack; class GVPixmap; class GVHistory; class GVScrollPixmapView; class GVSlideShow; class GVMetaEdit; class StatusBarProgress; class GVMainWindow : public KDockMainWindow { Q_OBJECT public: GVMainWindow(); GVFileViewStack* fileViewStack() const { return mFileViewStack; } GVScrollPixmapView* pixmapView() const { return mPixmapView; } bool showMenuBarInFullScreen() const { return mShowMenuBarInFullScreen; } bool showToolBarInFullScreen() const { return mShowToolBarInFullScreen; } bool showStatusBarInFullScreen() const { return mShowStatusBarInFullScreen; } GVPixmap* gvPixmap() const { return mGVPixmap; } void setShowMenuBarInFullScreen(bool); void setShowToolBarInFullScreen(bool); void setShowStatusBarInFullScreen(bool); public slots: void setURL(const KURL&,const QString&); protected: bool queryClose(); private: KDockWidget* mFolderDock; KDockWidget* mFileDock; KDockWidget* mPixmapDock; KDockWidget* mMetaDock; StatusBarProgress* mProgress; KToolBar* mMainToolBar; KToolBar* mLocationToolBar; QLabel* mSBDirLabel; QLabel* mSBDetailLabel; GVFileViewStack* mFileViewStack; GVDirView* mDirView; GVScrollPixmapView* mPixmapView; GVMetaEdit *mMetaEdit; GVPixmap* mGVPixmap; GVHistory* mGVHistory; GVSlideShow* mSlideShow; KAction* mOpenFile; KAction* mRenameFile; KAction* mCopyFiles; KAction* mMoveFiles; KAction* mDeleteFiles; KAction* mShowConfigDialog; KAction* mShowKeyDialog; KToggleAction* mToggleFullScreen; KAction* mStop; + KAction* mReload; KAction* mOpenHomeDir; KToolBarPopupAction* mGoUp; KAction* mShowFileProperties; KToggleAction* mToggleSlideShow; KAction* mRotateLeft; KAction* mRotateRight; KAction* mMirror; KAction* mFlip; KAction* mSaveFile; KAction* mSaveFileAs; KAction* mFilePrint; KAction* mToggleDirAndFileViews; KHistoryCombo* mURLEdit; KURLCompletion* mURLEditCompletion; QPtrList mWindowListActions; bool mShowMenuBarInFullScreen; bool mShowToolBarInFullScreen; bool mShowStatusBarInFullScreen; void hideToolBars(); void showToolBars(); void createWidgets(); void createActions(); void createLocationToolBar(); void createConnections(); void readConfig(KConfig*,const QString&); void writeConfig(KConfig*,const QString&) const; private slots: void goUp(); void goUpTo(int); void openParentDir(); void openHomeDir(); void renameFile(); void copyFiles(); void moveFiles(); void deleteFiles(); void showFileProperties(); void openFile(); void printFile(); /** print the actual file */ void toggleFullScreen(); void showConfigDialog(); void showExternalToolDialog(); void showKeyDialog(); void showToolBarDialog(); void applyMainWindowSettings(); void pixmapLoading(); void toggleSlideShow(); void toggleDirAndFileViews(); void slotDirRenamed(const KURL& oldURL, const KURL& newURL); /** * Update status bar and caption */ void updateStatusInfo(); /** * Update only caption, allows setting file info * when folder info is not available yet */ void updateFileInfo(); void thumbnailUpdateStarted(int); void thumbnailUpdateEnded(); void thumbnailUpdateProcessedOne(); /** * Allow quitting full screen mode by pressing Escape key. */ void escapePressed(); /** * Address bar related */ void slotURLEditChanged(const QString &str); void slotGo(); void updateWindowActions(); // Helper function for updateWindowActions() void createHideShowAction(KDockWidget* dock); }; #endif Index: trunk/kdeextragear-1/gwenview/src/gvmetaedit.cpp =================================================================== --- trunk/kdeextragear-1/gwenview/src/gvmetaedit.cpp (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gvmetaedit.cpp (revision 263335) @@ -1,176 +1,176 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab /* Copyright (c) 2003 Jos van den Oever This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Qt #include #include #include // KDE #include #include #include // Local #include "gvpixmap.h" #include "gvmetaedit.moc" const char* JPEG_EXIF_DATA="Jpeg EXIF Data"; const char* JPEG_EXIF_COMMENT="Comment"; const char* PNG_COMMENT="Comment"; GVMetaEdit::GVMetaEdit(QWidget *parent, GVPixmap *gvp, const char *name) : QVBox(parent, name) , mGVPixmap(gvp) , mMetaInfo(0L) { mCommentEdit=new QTextEdit(this); mCommentEdit->installEventFilter(this); connect(mCommentEdit, SIGNAL(modificationChanged(bool)), this, SLOT(setModified(bool))); - connect(mGVPixmap,SIGNAL(urlChanged(const KURL&,const QString&)), + connect(mGVPixmap,SIGNAL(loaded(const KURL&, const QString&)), this,SLOT(updateContent()) ); updateContent(); } GVMetaEdit::~GVMetaEdit() { clearData(); } bool GVMetaEdit::eventFilter(QObject *o, QEvent *e) { if (o == mCommentEdit && mEmpty && mWritable) { if (e->type() == QEvent::FocusIn) { mCommentEdit->setTextFormat(QTextEdit::PlainText); mCommentEdit->setText(""); } else if (e->type() == QEvent::FocusOut) { setEmptyText(); } } return false; } void GVMetaEdit::setModified(bool m) { if (m && mEmpty) { mEmpty = false; } } void GVMetaEdit::updateContent() { clearData(); if (mGVPixmap->isNull()) { mCommentEdit->setTextFormat(QTextEdit::RichText); mCommentEdit->setText(i18n("No image selected.")); //mCommentEdit->setEnabled(false); mEmpty = true; mWritable = false; return; } KURL url = mGVPixmap->url(); // make KFileMetaInfo object and check if file is writable #if KDE_VERSION_MAJOR >= 3 && KDE_VERSION_MINOR >= 2 mMetaInfo = new KFileMetaInfo(url); if (url.isLocalFile()) { mWritable = QFileInfo(url.path()).isWritable(); } else { mWritable = false; } #else // KDE <= 3.1 can only get meta info from local files mMetaInfo = new KFileMetaInfo(url.path()); mWritable = QFileInfo(url.path()).isWritable(); #endif // retrieve comment item QString mimetype = ""; if (!mMetaInfo->isEmpty()) { mimetype = mMetaInfo->mimeType(); } if (mimetype == "image/jpeg") { mCommentItem = (*mMetaInfo)[JPEG_EXIF_DATA][JPEG_EXIF_COMMENT]; } else if (mimetype == "image/png") { // we take the first comment QString name = (*mMetaInfo)[PNG_COMMENT].keys()[0]; mCommentItem = (*mMetaInfo)[PNG_COMMENT][name]; mWritable = false; // not implemented in KDE } else { mCommentItem = KFileMetaInfoItem(); mWritable = false; } /* Some code to debug QStringList k,l; k = mMetaInfo->groups(); for (uint i=0; isetTextFormat(QTextEdit::PlainText); mCommentEdit->setText(comment); } } else { mCommentEdit->setTextFormat(QTextEdit::RichText); mCommentEdit->setText("This image can't be commented."); } mCommentEdit->setReadOnly(!mWritable); mCommentEdit->setEnabled(mWritable); } void GVMetaEdit::clearData() { if (!mMetaInfo) return; // save changed data if (mWritable && mCommentEdit->isModified()) { mCommentItem.setValue(mCommentEdit->text()); mMetaInfo->applyChanges(); mCommentEdit->setModified(false); } delete mMetaInfo; mMetaInfo = 0L; } void GVMetaEdit::setEmptyText() { QString comment; mCommentEdit->setTextFormat(QTextEdit::RichText); if (mWritable) { comment=i18n("Type here to add a comment to this image."); } else { comment=i18n("No comment available."); } mCommentEdit->setText(comment); } Index: trunk/kdeextragear-1/gwenview/src/gvscrollpixmapview.cpp =================================================================== --- trunk/kdeextragear-1/gwenview/src/gvscrollpixmapview.cpp (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gvscrollpixmapview.cpp (revision 263335) @@ -1,964 +1,964 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab /* Gwenview - A simple image viewer for KDE Copyright 2000-2003 Aurélien Gâteau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include // Qt includes #include #include #include #include #include #include #include #include #include #include #include // KDE includes #include #include #include #include #include #include #include // Our includes #include "fileoperation.h" #include "gvexternaltoolmanager.h" #include "gvexternaltoolcontext.h" #include "gvpixmap.h" #include "gvscrollpixmapview.moc" const char* CONFIG_SHOW_PATH="show path"; const char* CONFIG_SMOOTH_SCALE="smooth scale"; const char* CONFIG_ENLARGE_SMALL_IMAGES="enlarge small images"; const char* CONFIG_SHOW_SCROLL_BARS="show scroll bars"; const char* CONFIG_LOCK_ZOOM="lock zoom"; const char* CONFIG_AUTO_ZOOM="auto zoom"; const char* CONFIG_MOUSE_BEHAVIOUR_NONE= "mouse behaviour none"; const char* CONFIG_MOUSE_BEHAVIOUR_SHIFT= "mouse behaviour shift"; const char* CONFIG_MOUSE_BEHAVIOUR_CONTROL="mouse behaviour control"; const char* CONFIG_MOUSE_BEHAVIOUR_ALT= "mouse behaviour alt"; const int AUTO_HIDE_TIMEOUT=2000; const double MAX_ZOOM=16.0; // Same value as GIMP //------------------------------------------------------------------------ // // GVScrollPixmapView ToolControllers // //------------------------------------------------------------------------ class GVScrollPixmapView::ToolController { protected: GVScrollPixmapView* mView; // Helper function QCursor loadCursor(const QString& name) { QString path; path=locate("appdata", QString("cursors/%1.png").arg(name)); return QCursor(QPixmap(path)); } public: ToolController(GVScrollPixmapView* view) : mView(view) {} virtual ~ToolController() {} virtual void mousePressEvent(QMouseEvent*) {} virtual void mouseMoveEvent(QMouseEvent*) {} virtual void mouseReleaseEvent(QMouseEvent*) {} virtual void wheelEvent(QWheelEvent* event) { event->accept(); } virtual void updateCursor() { mView->viewport()->setCursor(ArrowCursor); } }; class GVScrollPixmapView::ScrollToolController : public GVScrollPixmapView::ToolController { int mScrollStartX,mScrollStartY; bool mDragStarted; QCursor mDragCursor,mDraggingCursor; public: ScrollToolController(GVScrollPixmapView* view) : ToolController(view) , mScrollStartX(0), mScrollStartY(0) , mDragStarted(false) { mDragCursor=loadCursor("drag"); mDraggingCursor=loadCursor("dragging"); } void mousePressEvent(QMouseEvent* event) { mScrollStartX=event->x(); mScrollStartY=event->y(); mView->viewport()->setCursor(mDraggingCursor); mDragStarted=true; } void mouseMoveEvent(QMouseEvent* event) { if (!mDragStarted) return; int deltaX,deltaY; deltaX=mScrollStartX - event->x(); deltaY=mScrollStartY - event->y(); mScrollStartX=event->x(); mScrollStartY=event->y(); mView->scrollBy(deltaX,deltaY); } void mouseReleaseEvent(QMouseEvent*) { if (!mDragStarted) return; mDragStarted=false; mView->viewport()->setCursor(mDragCursor); } void wheelEvent(QWheelEvent* event) { mView->QScrollView::wheelEvent(event); } void updateCursor() { if (mDragStarted) { mView->viewport()->setCursor(mDraggingCursor); } else { mView->viewport()->setCursor(mDragCursor); } } }; class GVScrollPixmapView::ZoomToolController : public GVScrollPixmapView::ToolController { QCursor mZoomCursor; QCursor mAutoZoomCursor; public: ZoomToolController(GVScrollPixmapView* view) : ToolController(view) { mZoomCursor=loadCursor("zoom"); mAutoZoomCursor=loadCursor("autozoom"); } void mouseReleaseEvent(QMouseEvent*) { mView->autoZoom()->activate(); updateCursor(); } void wheelEvent(QWheelEvent* event) { if (event->delta()<0) { if (mView->zoomIn()->isEnabled()) mView->zoomIn()->activate(); } else { if (mView->zoomOut()->isEnabled()) mView->zoomOut()->activate(); } event->accept(); } void updateCursor() { // This is inverted, since we show the cursor for the tool which will // be activated *after* the click if (mView->autoZoom()->isChecked()) { mView->viewport()->setCursor(mZoomCursor); } else { mView->viewport()->setCursor(mAutoZoomCursor); } } }; class GVScrollPixmapView::BrowseToolController : public GVScrollPixmapView::ToolController { QCursor mCursor; public: BrowseToolController(GVScrollPixmapView* view) : ToolController(view) { mCursor=loadCursor("browse"); } void mouseReleaseEvent(QMouseEvent*) { mView->emitSelectNext(); } void wheelEvent(QWheelEvent* event) { if (event->delta()<0) { mView->emitSelectNext(); } else { mView->emitSelectPrevious(); } event->accept(); } void updateCursor() { mView->viewport()->setCursor(mCursor); } }; //------------------------------------------------------------------------ // // GVScrollPixmapView implementation // //------------------------------------------------------------------------ GVScrollPixmapView::GVScrollPixmapView(QWidget* parent,GVPixmap* pixmap,KActionCollection* actionCollection) : QScrollView(parent,0L,WResizeNoErase|WRepaintNoErase) , mGVPixmap(pixmap) , mAutoHideTimer(new QTimer(this)) , mPathLabel(new QLabel(parent)) , mTool(None) , mXOffset(0),mYOffset(0) , mZoom(1) , mActionCollection(actionCollection) , mFullScreen(false) , mOperaLikePrevious(false) , mZoomBeforeAuto(1) { setFocusPolicy(StrongFocus); setFrameStyle(NoFrame); mToolControllers[None]=new ToolController(this); mToolControllers[Browse]=new BrowseToolController(this); mToolControllers[Scroll]=new ScrollToolController(this); mToolControllers[Zoom]=new ZoomToolController(this); // Init path label mPathLabel->setBackgroundColor(white); QFont font=mPathLabel->font(); font.setWeight(QFont::Bold); mPathLabel->setFont(font); mPathLabel->hide(); // Create actions mAutoZoom=new KToggleAction(i18n("&Auto Zoom"),"autozoom",0,mActionCollection,"view_zoom_auto"); connect(mAutoZoom,SIGNAL(toggled(bool)), this,SLOT(setAutoZoom(bool)) ); mZoomIn=KStdAction::zoomIn(this,SLOT(slotZoomIn()),mActionCollection); mZoomIn->setIcon("zoomin"); mZoomOut=KStdAction::zoomOut(this,SLOT(slotZoomOut()),mActionCollection); mZoomOut->setIcon("zoomout"); mResetZoom=KStdAction::actualSize(this,SLOT(slotResetZoom()),mActionCollection); mResetZoom->setIcon("actualsize"); mLockZoom=new KToggleAction(i18n("&Lock Zoom"),"lockzoom",0,mActionCollection,"view_zoom_lock"); // Connect to some interesting signals - connect(mGVPixmap,SIGNAL(urlChanged(const KURL&,const QString&)), + connect(mGVPixmap,SIGNAL(loaded(const KURL&,const QString&)), this,SLOT(slotURLChanged()) ); connect(mGVPixmap,SIGNAL(modified()), this,SLOT(slotModified()) ); connect(mAutoHideTimer,SIGNAL(timeout()), this,SLOT(hideCursor()) ); // To monitor key presses viewport()->installEventFilter(this); } GVScrollPixmapView::~GVScrollPixmapView() { delete mToolControllers[None]; delete mToolControllers[Browse]; delete mToolControllers[Scroll]; delete mToolControllers[Zoom]; } void GVScrollPixmapView::slotURLChanged() { mXOffset=0; mYOffset=0; if (mGVPixmap->isNull()) { resizeContents(0,0); viewport()->repaint(false); updateZoomActions(); return; } if (mAutoZoom->isChecked()) { setZoom(computeAutoZoom()); } else { if (mLockZoom->isChecked()) { updateContentSize(); updateImageOffset(); updateZoomActions(); viewport()->repaint(false); } else { setZoom(1.0); } horizontalScrollBar()->setValue(0); verticalScrollBar()->setValue(0); } if (mFullScreen && mShowPathInFullScreen) updatePathLabel(); } void GVScrollPixmapView::slotModified() { updateContentSize(); updateImageOffset(); updateZoomActions(); viewport()->repaint(false); } void GVScrollPixmapView::restartAutoHideTimer() { mAutoHideTimer->start(AUTO_HIDE_TIMEOUT,true); } //------------------------------------------------------------------------ // // Properties // //------------------------------------------------------------------------ void GVScrollPixmapView::setSmoothScale(bool value) { mSmoothScale=value; viewport()->update(); } void GVScrollPixmapView::setEnlargeSmallImages(bool value) { mEnlargeSmallImages=value; if (mAutoZoom->isChecked()) { setZoom(computeAutoZoom()); } } void GVScrollPixmapView::setShowPathInFullScreen(bool value) { mShowPathInFullScreen=value; } void GVScrollPixmapView::setShowScrollBars(bool value) { mShowScrollBars=value; updateScrollBarMode(); } void GVScrollPixmapView::setZoom(double zoom, int centerX, int centerY) { int viewWidth=visibleWidth(); int viewHeight=visibleHeight(); double oldZoom=mZoom; mZoom=zoom; viewport()->setUpdatesEnabled(false); updateContentSize(); // Find the coordinate of the center of the image // and center the view on it if (centerX==-1) { centerX=int( ((viewWidth/2+contentsX()-mXOffset)/oldZoom)*mZoom ); } if (centerY==-1) { centerY=int( ((viewHeight/2+contentsY()-mYOffset)/oldZoom)*mZoom ); } center(centerX,centerY); updateImageOffset(); updateZoomActions(); viewport()->setUpdatesEnabled(true); viewport()->repaint(false); emit zoomChanged(mZoom); } void GVScrollPixmapView::setFullScreen(bool fullScreen) { mFullScreen=fullScreen; viewport()->setMouseTracking(mFullScreen); if (mFullScreen) { viewport()->setBackgroundColor(black); restartAutoHideTimer(); } else { viewport()->setBackgroundMode(PaletteDark); mAutoHideTimer->stop(); mToolControllers[mTool]->updateCursor(); } if (mFullScreen && mShowPathInFullScreen) { updatePathLabel(); mPathLabel->show(); } else { mPathLabel->hide(); } } void GVScrollPixmapView::setButtonStateTool(ButtonState state, Tool tool) { mButtonStateToolMap[state]=tool; } void GVScrollPixmapView::updateDefaultCursor() { // We assume no modifier is pressed when this is called // FIXME: To be removed after ConfigDialog rewrite selectTool(NoButton); } //------------------------------------------------------------------------ // // Overloaded methods // //------------------------------------------------------------------------ void GVScrollPixmapView::resizeEvent(QResizeEvent* event) { QScrollView::resizeEvent(event); if (mAutoZoom->isChecked()) { setZoom(computeAutoZoom()); } else { updateContentSize(); updateImageOffset(); } } //#define DEBUG_RECTS inline int roundDown(int value,double factor) { return int(int(value/factor)*factor); } inline int roundUp(int value,double factor) { return int(ceil(value/factor)*factor); } inline void composite(uint* rgba,uint value) { uint alpha=(*rgba) >> 24; if (alpha<255) { uint alphaValue=(255-alpha)*value; uint c1=( ( (*rgba & 0xFF0000) >> 16 ) * alpha + alphaValue ) >> 8; uint c2=( ( (*rgba & 0x00FF00) >> 8 ) * alpha + alphaValue ) >> 8; uint c3=( ( (*rgba & 0x0000FF) >> 0 ) * alpha + alphaValue ) >> 8; *rgba=0xFF000000 + (c1<<16) + (c2<<8) + c3; } } void GVScrollPixmapView::drawContents(QPainter* painter,int clipx,int clipy,int clipw,int cliph) { #ifdef DEBUG_RECTS static QColor colors[4]={QColor(255,0,0),QColor(0,255,0),QColor(0,0,255),QColor(255,255,0) }; static int numColor=0; #endif if (mGVPixmap->isNull()) { painter->eraseRect(clipx,clipy,clipw,cliph); return; } QRect updateRect=QRect(clipx,clipy,clipw,cliph); // If we are enlarging the image, we grow the update rect so that it // contains full zoomed image pixels. We also take one more image pixel to // avoid gaps in images. if (mZoom>1.0) { updateRect.setLeft ( roundDown(updateRect.left(), mZoom)-int(mZoom) ); updateRect.setTop ( roundDown(updateRect.top(), mZoom)-int(mZoom) ); updateRect.setRight ( roundUp( updateRect.right(), mZoom)+int(mZoom)-1 ); updateRect.setBottom( roundUp( updateRect.bottom(),mZoom)+int(mZoom)-1 ); } QRect zoomedImageRect=QRect(mXOffset, mYOffset, int(mGVPixmap->width()*mZoom), int(mGVPixmap->height()*mZoom)); updateRect=updateRect.intersect(zoomedImageRect); if (updateRect.isEmpty()) return; QImage image(updateRect.size()/mZoom,32); image=mGVPixmap->image().copy( int(updateRect.x()/mZoom) - int(mXOffset/mZoom), int(updateRect.y()/mZoom) - int(mYOffset/mZoom), int(updateRect.width()/mZoom), int(updateRect.height()/mZoom) ); if (mSmoothScale) { image=image.smoothScale(updateRect.size()); } else { image=image.scale(updateRect.size()); } if (image.hasAlphaBuffer()) { bool light; int imageXOffset=int(updateRect.x())-int(mXOffset); int imageYOffset=int(updateRect.y())-int(mYOffset); int imageWidth=image.width(); int imageHeight=image.height(); for (int y=0;ybackgroundColor()); bufferPainter.eraseRect(0,0,clipw,cliph); bufferPainter.drawImage(updateRect.x()-clipx,updateRect.y()-clipy,image); } painter->drawPixmap(clipx,clipy,buffer); #ifdef DEBUG_RECTS painter->setPen(colors[numColor]); numColor=(numColor+1)%4; painter->drawRect(clipx,clipy,clipw,cliph); #endif } void GVScrollPixmapView::viewportMousePressEvent(QMouseEvent* event) { viewport()->setFocus(); if (event->button()==RightButton) return; mToolControllers[mTool]->mousePressEvent(event); } void GVScrollPixmapView::viewportMouseMoveEvent(QMouseEvent* event) { selectTool(event->state()); mToolControllers[mTool]->mouseMoveEvent(event); if (mFullScreen) { restartAutoHideTimer(); } } void GVScrollPixmapView::viewportMouseReleaseEvent(QMouseEvent* event) { switch (event->button()) { case Qt::LeftButton: if (event->stateAfter() & Qt::RightButton) { mOperaLikePrevious=true; emit selectPrevious(); return; } mToolControllers[mTool]->mouseReleaseEvent(event); break; case Qt::RightButton: if (event->stateAfter() & Qt::LeftButton) { emit selectNext(); return; } if (mOperaLikePrevious) { // Avoid showing the popup menu after Opera like previous mOperaLikePrevious=false; } else { // Don't show the menu if there's no image, except if we are in // fullscreen mode, so that we always have a way to leave it. if (!mGVPixmap->isNull() || mFullScreen) { openContextMenu(event->globalPos()); return; } } break; default: // Avoid compiler complain break; } } bool GVScrollPixmapView::eventFilter(QObject* obj, QEvent* event) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::AccelOverride: return viewportKeyEvent(static_cast(event)); default: break; } return QScrollView::eventFilter(obj,event); } bool GVScrollPixmapView::viewportKeyEvent(QKeyEvent* event) { selectTool(event->stateAfter()); if (mFullScreen) { restartAutoHideTimer(); } return false; } void GVScrollPixmapView::selectTool(ButtonState state) { ButtonState modifier=ButtonState(state & (ShiftButton | ControlButton | AltButton) ); mTool=mButtonStateToolMap[modifier]; mToolControllers[mTool]->updateCursor(); } void GVScrollPixmapView::wheelEvent(QWheelEvent* event) { mToolControllers[mTool]->wheelEvent(event); } //------------------------------------------------------------------------ // // Slots // //------------------------------------------------------------------------ void GVScrollPixmapView::slotZoomIn() { double newZoom; if (mZoom>=1.0) { newZoom=floor(mZoom)+1.0; } else { newZoom=1/( ceil(1/mZoom)-1.0 ); } if (mAutoZoom->isChecked()) { mAutoZoom->setChecked(false); updateScrollBarMode(); } setZoom(newZoom); } void GVScrollPixmapView::slotZoomOut() { double newZoom; if (mZoom>1.0) { newZoom=ceil(mZoom)-1.0; } else { newZoom=1/( floor(1/mZoom)+1.0 ); } if (mAutoZoom->isChecked()) { mAutoZoom->setChecked(false); updateScrollBarMode(); } setZoom(newZoom); } void GVScrollPixmapView::slotResetZoom() { if (mAutoZoom->isChecked()) { mAutoZoom->setChecked(false); updateScrollBarMode(); } setZoom(1.0); } void GVScrollPixmapView::setAutoZoom(bool value) { updateScrollBarMode(); if (value) { mZoomBeforeAuto=mZoom; mXCenterBeforeAuto=width()/2 + contentsX() + mXOffset; mYCenterBeforeAuto=height()/2 + contentsY() + mYOffset; setZoom(computeAutoZoom()); } else { setZoom(mZoomBeforeAuto, mXCenterBeforeAuto, mYCenterBeforeAuto); } } //------------------------------------------------------------------------ // // Private // //------------------------------------------------------------------------ void GVScrollPixmapView::openContextMenu(const QPoint& pos) { QPopupMenu menu(this); // The fullscreen item is always there, to be able to leave fullscreen mode // if necessary mActionCollection->action("fullscreen")->plug(&menu); if (!mGVPixmap->isNull()) { menu.insertSeparator(); mAutoZoom->plug(&menu); mZoomIn->plug(&menu); mZoomOut->plug(&menu); mResetZoom->plug(&menu); mLockZoom->plug(&menu); menu.insertSeparator(); mActionCollection->action("first")->plug(&menu); mActionCollection->action("previous")->plug(&menu); mActionCollection->action("next")->plug(&menu); mActionCollection->action("last")->plug(&menu); menu.insertSeparator(); QPopupMenu* editMenu=new QPopupMenu(&menu); mActionCollection->action("rotate_left")->plug(editMenu); mActionCollection->action("rotate_right")->plug(editMenu); mActionCollection->action("mirror")->plug(editMenu); mActionCollection->action("flip")->plug(editMenu); menu.insertItem( i18n("Edit"), editMenu ); GVExternalToolContext* externalToolContext= GVExternalToolManager::instance()->createContext( this, mGVPixmap->url()); menu.insertItem( i18n("External Tools"), externalToolContext->popupMenu()); menu.insertSeparator(); menu.connectItem( menu.insertItem( i18n("&Rename...") ), this,SLOT(renameFile()) ); menu.connectItem( menu.insertItem( i18n("&Copy To...") ), this,SLOT(copyFile()) ); menu.connectItem( menu.insertItem( i18n("&Move To...") ), this,SLOT(moveFile()) ); menu.connectItem( menu.insertItem( i18n("&Delete") ), this,SLOT(deleteFile()) ); menu.insertSeparator(); menu.connectItem( menu.insertItem( i18n("Properties") ), this,SLOT(showFileProperties()) ); } menu.exec(pos); } void GVScrollPixmapView::updateScrollBarMode() { if (mAutoZoom->isChecked() || !mShowScrollBars) { setVScrollBarMode(AlwaysOff); setHScrollBarMode(AlwaysOff); } else { setVScrollBarMode(Auto); setHScrollBarMode(Auto); } } void GVScrollPixmapView::updateContentSize() { resizeContents( int(mGVPixmap->width()*mZoom), int(mGVPixmap->height()*mZoom) ); } // QSize.scale() does not exist in Qt 3.0.x #if QT_VERSION<0x030100 static void sizeScaleMin(QSize* size, int w, int h) { int w0 = size->width(); int h0 = size->height(); int rw = h * w0 / h0; if ( rw <= w ) { size->setWidth( rw ); size->setHeight( h ); } else { size->setWidth( w ); size->setHeight( w * h0 / w0 ); } } #endif double GVScrollPixmapView::computeAutoZoom() { if (mGVPixmap->isNull()) { return 1.0; } QSize size=mGVPixmap->image().size(); #if QT_VERSION>=0x030100 size.scale(width(),height(),QSize::ScaleMin); #else sizeScaleMin(&size,width(),height()); #endif double zoom=double(size.width())/mGVPixmap->width(); if (zoom>1.0 && !mEnlargeSmallImages) return 1.0; return zoom; } void GVScrollPixmapView::updateImageOffset() { int viewWidth=width(); int viewHeight=height(); // Compute mXOffset and mYOffset in case the image does not fit // the view width or height int zpixWidth=int(mGVPixmap->width() * mZoom); int zpixHeight=int(mGVPixmap->height() * mZoom); if (zpixWidth>viewWidth) { viewHeight-=horizontalScrollBar()->height(); } if (zpixHeight>viewHeight) { viewWidth-=verticalScrollBar()->width(); } mXOffset=QMAX(0,(viewWidth-zpixWidth)/2); mYOffset=QMAX(0,(viewHeight-zpixHeight)/2); } void GVScrollPixmapView::hideCursor() { viewport()->setCursor(blankCursor); } void GVScrollPixmapView::updatePathLabel() { QString path=mGVPixmap->url().path(); QPainter painter; QSize pathSize=mPathLabel->fontMetrics().size(0,path); pathSize.setWidth( pathSize.width() + 4); pathSize.setHeight( pathSize.height() + 15); int left=2; int top=mPathLabel->fontMetrics().height(); // Create a mask for the text QBitmap mask(pathSize,true); painter.begin(&mask); painter.setFont(mPathLabel->font()); painter.drawText(left-1,top-1,path); painter.drawText(left,top-1,path); painter.drawText(left+1,top-1,path); painter.drawText(left-1,top,path); painter.drawText(left+1,top,path); painter.drawText(left-1,top+1,path); painter.drawText(left,top+1,path); painter.drawText(left+1,top+1,path); painter.end(); // Draw the text on a pixmap QPixmap pixmap(pathSize); painter.begin(&pixmap); painter.setFont(mPathLabel->font()); painter.eraseRect(pixmap.rect()); painter.setPen(black); painter.drawText(left,top,path); painter.end(); // Update the path label mPathLabel->setPixmap(pixmap); mPathLabel->setMask(mask); mPathLabel->adjustSize(); } void GVScrollPixmapView::updateZoomActions() { // Disable most actions if there's no image if (mGVPixmap->isNull()) { mZoomIn->setEnabled(false); mZoomOut->setEnabled(false); mResetZoom->setEnabled(false); return; } mAutoZoom->setEnabled(true); mResetZoom->setEnabled(true); if (mAutoZoom->isChecked()) { mZoomIn->setEnabled(true); mZoomOut->setEnabled(true); } else { mZoomIn->setEnabled(mZoomsetEnabled(mZoom>1/MAX_ZOOM); } } //------------------------------------------------------------------------ // // File operations // //------------------------------------------------------------------------ void GVScrollPixmapView::showFileProperties() { (void)new KPropertiesDialog(mGVPixmap->url()); } void GVScrollPixmapView::renameFile() { FileOperation::rename(mGVPixmap->url(),this); } void GVScrollPixmapView::copyFile() { KURL::List list; list << mGVPixmap->url(); FileOperation::copyTo(list,this); } void GVScrollPixmapView::moveFile() { KURL::List list; list << mGVPixmap->url(); FileOperation::moveTo(list,this); } void GVScrollPixmapView::deleteFile() { KURL::List list; list << mGVPixmap->url(); FileOperation::del(list,this); } //------------------------------------------------------------------------ // // Config // //------------------------------------------------------------------------ void GVScrollPixmapView::readConfig(KConfig* config, const QString& group) { config->setGroup(group); mShowPathInFullScreen=config->readBoolEntry(CONFIG_SHOW_PATH,true); mSmoothScale=config->readBoolEntry(CONFIG_SMOOTH_SCALE,false); mEnlargeSmallImages=config->readBoolEntry(CONFIG_ENLARGE_SMALL_IMAGES,false); mShowScrollBars=config->readBoolEntry(CONFIG_SHOW_SCROLL_BARS,true); mAutoZoom->setChecked(config->readBoolEntry(CONFIG_AUTO_ZOOM,false)); updateScrollBarMode(); mLockZoom->setChecked(config->readBoolEntry(CONFIG_LOCK_ZOOM,false)); mButtonStateToolMap[NoButton]= Tool( config->readNumEntry(CONFIG_MOUSE_BEHAVIOUR_NONE,Scroll) ); mButtonStateToolMap[ControlButton]=Tool( config->readNumEntry(CONFIG_MOUSE_BEHAVIOUR_CONTROL,Browse) ); mButtonStateToolMap[ShiftButton]= Tool( config->readNumEntry(CONFIG_MOUSE_BEHAVIOUR_SHIFT,Zoom) ); mButtonStateToolMap[AltButton]= Tool( config->readNumEntry(CONFIG_MOUSE_BEHAVIOUR_ALT,None) ); mTool=mButtonStateToolMap[NoButton]; mToolControllers[mTool]->updateCursor(); } void GVScrollPixmapView::writeConfig(KConfig* config, const QString& group) const { config->setGroup(group); config->writeEntry(CONFIG_SHOW_PATH,mShowPathInFullScreen); config->writeEntry(CONFIG_SMOOTH_SCALE,mSmoothScale); config->writeEntry(CONFIG_ENLARGE_SMALL_IMAGES,mEnlargeSmallImages); config->writeEntry(CONFIG_SHOW_SCROLL_BARS,mShowScrollBars); config->writeEntry(CONFIG_AUTO_ZOOM,mAutoZoom->isChecked()); config->writeEntry(CONFIG_LOCK_ZOOM,mLockZoom->isChecked()); config->writeEntry(CONFIG_MOUSE_BEHAVIOUR_NONE , int(mButtonStateToolMap[NoButton]) ); config->writeEntry(CONFIG_MOUSE_BEHAVIOUR_CONTROL, int(mButtonStateToolMap[ControlButton]) ); config->writeEntry(CONFIG_MOUSE_BEHAVIOUR_SHIFT , int(mButtonStateToolMap[ShiftButton]) ); config->writeEntry(CONFIG_MOUSE_BEHAVIOUR_ALT , int(mButtonStateToolMap[AltButton]) ); } Index: trunk/kdeextragear-1/gwenview/src/gvmainwindow.cpp =================================================================== --- trunk/kdeextragear-1/gwenview/src/gvmainwindow.cpp (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gvmainwindow.cpp (revision 263335) @@ -1,896 +1,899 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab /* Gwenview - A simple image viewer for KDE Copyright 2000-2003 Aurélien Gâteau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Qt #include #include #include #include #include // KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Local #include "configdialog.h" #include "fileoperation.h" #include "gvbookmarkowner.h" #include "gvdirview.h" #include "gvexternaltooldialog.h" #include "gvfileviewstack.h" #include "gvhistory.h" #include "gvjpegtran.h" #include "gvpixmap.h" #include "gvscrollpixmapview.h" #include "gvslideshow.h" #include "gvslideshowdialog.h" #include "statusbarprogress.h" #include "gvmetaedit.h" #if KDE_VERSION < 0x30100 #include "libgvcompat/kwidgetaction.h" #endif #include "gvmainwindow.moc" const char* CONFIG_DOCK_GROUP="dock"; const char* CONFIG_GVPIXMAP_GROUP="misc"; const char* CONFIG_MAINWINDOW_GROUP="main window"; const char* CONFIG_FILEWIDGET_GROUP="file widget"; const char* CONFIG_JPEGTRAN_GROUP="jpegtran"; const char* CONFIG_PIXMAPWIDGET_GROUP="pixmap widget"; const char* CONFIG_FILEOPERATION_GROUP="file operations"; const char* CONFIG_SLIDESHOW_GROUP="slide show"; const char* CONFIG_MENUBAR_IN_FS="menu bar in full screen"; const char* CONFIG_TOOLBAR_IN_FS="tool bar in full screen"; const char* CONFIG_STATUSBAR_IN_FS="status bar in full screen"; const char* CONFIG_SHOW_LOCATION_TOOLBAR="show address bar"; GVMainWindow::GVMainWindow() : KDockMainWindow(), mProgress(0L), mLocationToolBar(0L) { FileOperation::readConfig(KGlobal::config(),CONFIG_FILEOPERATION_GROUP); readConfig(KGlobal::config(),CONFIG_MAINWINDOW_GROUP); // Backend mGVPixmap=new GVPixmap(this); mGVHistory=new GVHistory(mGVPixmap, actionCollection()); // GUI createWidgets(); createActions(); createLocationToolBar(); // This event filter is here to make sure the pixmap view is aware of the changes // in the keyboard modifiers, even if it isn't focused kapp->installEventFilter(mPixmapView); #if KDE_VERSION >= 0x30100 setStandardToolBarMenuEnabled(true); #endif createGUI("gwenviewui.rc", false); createConnections(); mWindowListActions.setAutoDelete(true); updateWindowActions(); applyMainWindowSettings(); mFileViewStack->setFocus(); // Command line KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); KURL url; if (args->count()==0) { url.setPath( QDir::currentDirPath() ); } else { url=args->url(0); } // Check if we should start in fullscreen mode if (args->isSet("f")) { mToggleFullScreen->activate(); } // Go to requested file mGVPixmap->setURL(url); } bool GVMainWindow::queryClose() { if (!mGVPixmap->saveIfModified()) return false; KConfig* config=KGlobal::config(); FileOperation::writeConfig(config, CONFIG_FILEOPERATION_GROUP); mPixmapView->writeConfig(config, CONFIG_PIXMAPWIDGET_GROUP); mFileViewStack->writeConfig(config, CONFIG_FILEWIDGET_GROUP); mSlideShow->writeConfig(config, CONFIG_SLIDESHOW_GROUP); GVJPEGTran::writeConfig(config, CONFIG_JPEGTRAN_GROUP); // Don't store dock layout if only the image dock is visible. This avoid // saving layout when in "fullscreen" or "image only" mode. if (mFileViewStack->isVisible() || mDirView->isVisible()) { writeDockConfig(config,CONFIG_DOCK_GROUP); } writeConfig(config,CONFIG_MAINWINDOW_GROUP); // If we are in fullscreen mode, we need to make the needed GUI elements // visible before saving the window settings. if (mToggleFullScreen->isChecked()) { statusBar()->show(); if (toolBar()->area()) { toolBar()->area()->show(); } else { toolBar()->show(); } leftDock()->show(); rightDock()->show(); topDock()->show(); bottomDock()->show(); menuBar()->show(); } saveMainWindowSettings(KGlobal::config(), "MainWindow"); return true; } //----------------------------------------------------------------------- // // Public slots // //----------------------------------------------------------------------- void GVMainWindow::setURL(const KURL& url,const QString&) { //kdDebug() << "GVMainWindow::setURL " << url.path() << " - " << filename << endl; bool filenameIsValid=!mGVPixmap->isNull(); mRenameFile->setEnabled(filenameIsValid); mCopyFiles->setEnabled(filenameIsValid); mMoveFiles->setEnabled(filenameIsValid); mDeleteFiles->setEnabled(filenameIsValid); mShowFileProperties->setEnabled(filenameIsValid); mRotateLeft->setEnabled(filenameIsValid); mRotateRight->setEnabled(filenameIsValid); mMirror->setEnabled(filenameIsValid); mFlip->setEnabled(filenameIsValid); mSaveFile->setEnabled(filenameIsValid); mSaveFileAs->setEnabled(filenameIsValid); mFilePrint->setEnabled(filenameIsValid); + mReload->setEnabled(filenameIsValid); QPopupMenu *upPopup = mGoUp->popupMenu(); upPopup->clear(); int i = 0; KURL urlUp = url.upURL(); while(urlUp.hasPath()) { upPopup->insertItem(urlUp.url()), urlUp.prettyURL(); if(urlUp.path() == "/" || ++i > 10) break; urlUp = urlUp.upURL(); } mGoUp->setEnabled(url.path() != "/"); updateStatusInfo(); kapp->restoreOverrideCursor(); mURLEditCompletion->addItem(url.prettyURL()); mURLEdit->setEditText(url.prettyURL()); mURLEdit->addToHistory(url.prettyURL()); } void GVMainWindow::goUp() { goUpTo(mGoUp->popupMenu()->idAt(0)); } void GVMainWindow::goUpTo(int id) { mGVPixmap->setDirURL((KURL)mGoUp->popupMenu()->text(id)); } //----------------------------------------------------------------------- // // File operations // //----------------------------------------------------------------------- void GVMainWindow::openParentDir() { KURL url=mGVPixmap->dirURL().upURL(); mGVPixmap->setURL(url); } void GVMainWindow::openHomeDir() { KURL url; url.setPath( QDir::homeDirPath() ); mGVPixmap->setURL(url); } void GVMainWindow::renameFile() { if (mFileViewStack->isVisible()) { mFileViewStack->renameFile(); } else { mPixmapView->renameFile(); } } void GVMainWindow::copyFiles() { if (mFileViewStack->isVisible()) { mFileViewStack->copyFiles(); } else { mPixmapView->copyFile(); } } void GVMainWindow::moveFiles() { if (mFileViewStack->isVisible()) { mFileViewStack->moveFiles(); } else { mPixmapView->moveFile(); } } void GVMainWindow::deleteFiles() { if (mFileViewStack->isVisible()) { mFileViewStack->deleteFiles(); } else { mPixmapView->deleteFile(); } } void GVMainWindow::showFileProperties() { if (mFileViewStack->isVisible()) { mFileViewStack->showFileProperties(); } else { mPixmapView->showFileProperties(); } } void GVMainWindow::openFile() { KURL url=KFileDialog::getOpenURL(); if (!url.isValid()) return; mGVPixmap->setURL(url); } void GVMainWindow::printFile() { KPrinter printer; if (printer.setup(this)) { mGVPixmap->print(&printer); } } //----------------------------------------------------------------------- // // Private slots // //----------------------------------------------------------------------- void GVMainWindow::pixmapLoading() { kapp->setOverrideCursor(QCursor(WaitCursor)); } void GVMainWindow::toggleDirAndFileViews() { KConfig* config=KGlobal::config(); if (mFileDock->isVisible() || mFolderDock->isVisible()) { writeDockConfig(config,CONFIG_DOCK_GROUP); makeDockInvisible(mFileDock); makeDockInvisible(mFolderDock); } else { readDockConfig(config,CONFIG_DOCK_GROUP); } mPixmapView->setFocus(); } void GVMainWindow::hideToolBars() { QPtrListIterator it=toolBarIterator(); KToolBar* bar; for(;it.current()!=0L; ++it) { bar=it.current(); if (bar->area()) { bar->area()->hide(); } else { bar->hide(); } } } void GVMainWindow::showToolBars() { QPtrListIterator it=toolBarIterator(); KToolBar* bar; for(;it.current()!=0L; ++it) { bar=it.current(); if (bar->area()) { bar->area()->show(); } else { bar->show(); } } } void GVMainWindow::toggleFullScreen() { KConfig* config=KGlobal::config(); mToggleDirAndFileViews->setEnabled(!mToggleFullScreen->isChecked()); if (mToggleFullScreen->isChecked()) { if (!mShowMenuBarInFullScreen) menuBar()->hide(); /* Hide toolbar * If the toolbar is docked we hide the DockArea to avoid * having a one pixel band remaining * For the same reason, we hide all the empty DockAreas * * NOTE: This does not work really well if the toolbar is in * the left or right dock area. */ if (!mShowToolBarInFullScreen) { hideToolBars(); } if (leftDock()->isEmpty()) leftDock()->hide(); if (rightDock()->isEmpty()) rightDock()->hide(); if (topDock()->isEmpty()) topDock()->hide(); if (bottomDock()->isEmpty()) bottomDock()->hide(); if (!mShowStatusBarInFullScreen) statusBar()->hide(); writeDockConfig(config,CONFIG_DOCK_GROUP); makeDockInvisible(mFileDock); makeDockInvisible(mFolderDock); makeDockInvisible(mMetaDock); mPixmapView->setFullScreen(true); showFullScreen(); } else { readDockConfig(config,CONFIG_DOCK_GROUP); statusBar()->show(); showToolBars(); leftDock()->show(); rightDock()->show(); topDock()->show(); bottomDock()->show(); menuBar()->show(); mPixmapView->setFullScreen(false); showNormal(); } mPixmapView->setFocus(); } void GVMainWindow::toggleSlideShow() { if (mToggleSlideShow->isChecked()) { GVSlideShowDialog dialog(this,mSlideShow); if (!dialog.exec()) { mToggleSlideShow->setChecked(false); return; } if (!mToggleFullScreen->isChecked()) { mToggleFullScreen->activate(); } mSlideShow->start(); } else { mSlideShow->stop(); if (mToggleFullScreen->isChecked()) { mToggleFullScreen->activate(); } } } void GVMainWindow::showConfigDialog() { ConfigDialog dialog(this,this); dialog.exec(); } void GVMainWindow::showExternalToolDialog() { GVExternalToolDialog* dialog=new GVExternalToolDialog(this); dialog->show(); } void GVMainWindow::showKeyDialog() { KKeyDialog::configure(actionCollection()); } void GVMainWindow::showToolBarDialog() { saveMainWindowSettings(KGlobal::config(), "MainWindow"); KEditToolbar dlg(actionCollection()); connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(applyMainWindowSettings())); if (dlg.exec()) { createGUI(); } } void GVMainWindow::applyMainWindowSettings() { KMainWindow::applyMainWindowSettings(KGlobal::config(), "MainWindow"); } void GVMainWindow::escapePressed() { if (mToggleSlideShow->isChecked()) { mToggleSlideShow->activate(); return; } if (mToggleFullScreen->isChecked()) { mToggleFullScreen->activate(); } } void GVMainWindow::thumbnailUpdateStarted(int count) { mProgress=new StatusBarProgress(statusBar(),i18n("Generating thumbnails..."),count); mProgress->progress()->setFormat("%v/%m"); mProgress->show(); mStop->setEnabled(true); } void GVMainWindow::thumbnailUpdateEnded() { mStop->setEnabled(false); if (mProgress) { mProgress->hide(); delete mProgress; mProgress=0L; } } void GVMainWindow::thumbnailUpdateProcessedOne() { mProgress->progress()->advance(1); } void GVMainWindow::slotURLEditChanged(const QString &str) { mGVPixmap->setURL(str); if (mFileViewStack->isVisible()) { mFileViewStack->setFocus(); } else if (mPixmapView->isVisible()) { mPixmapView->setFocus(); } } void GVMainWindow::slotDirRenamed(const KURL& oldURL, const KURL& newURL) { kdDebug() << "GVMainWindow::slotDirRenamed: " << oldURL.prettyURL() << " to " << newURL.prettyURL() << endl; KURL url(mGVPixmap->url()); if (!oldURL.isParentOf(url) ) return; QString oldPath=oldURL.path(); kdDebug() << " current path: " << url.path() << endl; QString path=newURL.path() + url.path().mid(oldPath.length()); kdDebug() << " new path: " << path << endl; url.setPath(path); mGVPixmap->setURL(url); } void GVMainWindow::slotGo() { mGVPixmap->setURL(mURLEdit->currentText()); } //----------------------------------------------------------------------- // // GUI // //----------------------------------------------------------------------- void GVMainWindow::updateStatusInfo() { QString txt; uint count=mFileViewStack->fileCount(); QString url=mGVPixmap->dirURL().prettyURL(); if (count==0) { txt=i18n("%1 - No Images").arg(url); } else { txt=i18n("%1 - One Image","%1 - %n images",count).arg(url); } mSBDirLabel->setText(txt); updateFileInfo(); } void GVMainWindow::updateFileInfo() { QString filename=mGVPixmap->filename(); if (!filename.isEmpty()) { QString info=QString("%1 %2x%3 @ %4%") .arg(filename).arg(mGVPixmap->width()).arg(mGVPixmap->height()) .arg(int(mPixmapView->zoom()*100) ); mSBDetailLabel->show(); mSBDetailLabel->setText(info); } else { mSBDetailLabel->hide(); } setCaption(filename); } void GVMainWindow::createWidgets() { KConfig* config=KGlobal::config(); manager()->setSplitterHighResolution(true); manager()->setSplitterOpaqueResize(true); // Status bar mSBDirLabel=new KSqueezedTextLabel("", statusBar()); statusBar()->addWidget(mSBDirLabel,1); mSBDetailLabel=new QLabel("", statusBar()); statusBar()->addWidget(mSBDetailLabel); // Pixmap widget mPixmapDock = createDockWidget("Image",SmallIcon("gwenview"),NULL,i18n("Image")); mPixmapView=new GVScrollPixmapView(mPixmapDock,mGVPixmap,actionCollection()); mPixmapDock->setWidget(mPixmapView); setView(mPixmapDock); setMainDockWidget(mPixmapDock); // Folder widget mFolderDock = createDockWidget("Folders",SmallIcon("folder_open"),NULL,i18n("Folders")); mDirView=new GVDirView(mFolderDock); mFolderDock->setWidget(mDirView); // File widget mFileDock = createDockWidget("Files",SmallIcon("image"),NULL,i18n("Files")); mFileViewStack=new GVFileViewStack(this,actionCollection()); mFileDock->setWidget(mFileViewStack); // Meta info edit widget mMetaDock = createDockWidget("File Attributes", SmallIcon("doc"),NULL, i18n("File Info")); mMetaEdit = new GVMetaEdit(mMetaDock, mGVPixmap); mMetaDock->setWidget(mMetaEdit); // Slide show controller (not really a widget) mSlideShow=new GVSlideShow(mFileViewStack->selectFirst(),mFileViewStack->selectNext()); // Default dock config setGeometry(20,20,600,400); mFolderDock->manualDock( mPixmapDock,KDockWidget::DockLeft,30); mFileDock->manualDock( mPixmapDock,KDockWidget::DockTop,30); mMetaDock->manualDock( mPixmapDock,KDockWidget::DockTop,30); // Load config readDockConfig(config,CONFIG_DOCK_GROUP); mFileViewStack->readConfig(config,CONFIG_FILEWIDGET_GROUP); mPixmapView->readConfig(config,CONFIG_PIXMAPWIDGET_GROUP); mSlideShow->readConfig(config,CONFIG_SLIDESHOW_GROUP); GVJPEGTran::readConfig(config,CONFIG_JPEGTRAN_GROUP); } void GVMainWindow::createActions() { // File mOpenFile=KStdAction::open(this,SLOT(openFile()),actionCollection() ); mSaveFile=KStdAction::save(mGVPixmap,SLOT(save()),actionCollection() ); mSaveFileAs=KStdAction::saveAs(mGVPixmap,SLOT(saveAs()),actionCollection() ); mFilePrint = KStdAction::print(this, SLOT(printFile()), actionCollection()); mRenameFile=new KAction(i18n("&Rename..."),Key_F2,this,SLOT(renameFile()),actionCollection(),"file_rename"); - mCopyFiles=new KAction(i18n("&Copy To..."),Key_F5,this,SLOT(copyFiles()),actionCollection(),"file_copy"); - mMoveFiles=new KAction(i18n("&Move To..."),Key_F6,this,SLOT(moveFiles()),actionCollection(),"file_move"); + mCopyFiles=new KAction(i18n("&Copy To..."),Key_F7,this,SLOT(copyFiles()),actionCollection(),"file_copy"); + mMoveFiles=new KAction(i18n("&Move To..."),Key_F8,this,SLOT(moveFiles()),actionCollection(),"file_move"); mDeleteFiles=new KAction(i18n("&Delete"),"editdelete",Key_Delete,this,SLOT(deleteFiles()),actionCollection(),"file_delete"); mShowFileProperties=new KAction(i18n("Properties"),0,this,SLOT(showFileProperties()),actionCollection(),"file_properties"); KStdAction::quit( kapp, SLOT (closeAllWindows()), actionCollection() ); // Edit mRotateLeft=new KAction(i18n("Rotate &Left"),"rotate_left",CTRL + Key_L,mGVPixmap,SLOT(rotateLeft()),actionCollection(),"rotate_left"); mRotateRight=new KAction(i18n("Rotate &Right"),"rotate_right",CTRL + Key_R,mGVPixmap,SLOT(rotateRight()),actionCollection(),"rotate_right"); mMirror=new KAction(i18n("&Mirror"),"mirror",0,mGVPixmap,SLOT(mirror()),actionCollection(),"mirror"); mFlip=new KAction(i18n("&Flip"),"flip",0,mGVPixmap,SLOT(flip()),actionCollection(),"flip"); // View - mStop=new KAction(i18n("Stop"),"stop",Key_Escape,mFileViewStack,SLOT(cancel()),actionCollection(),"stop"); + mReload=new KAction(i18n("Reload"), "reload", Key_F5, mGVPixmap, SLOT(reload()), actionCollection(), "reload"); + mReload->setEnabled(false); + mStop=new KAction(i18n("Stop"),"stop",Key_Escape,mFileViewStack,SLOT(cancel()),actionCollection(), "stop"); mStop->setEnabled(false); //(0x3015A == 3.1.90) #if KDE_VERSION>=0x3015A mToggleFullScreen= KStdAction::fullScreen(this,SLOT(toggleFullScreen()),actionCollection(),0); #else mToggleFullScreen=new KToggleAction(i18n("Full Screen"),"window_fullscreen",CTRL + Key_F,this,SLOT(toggleFullScreen()),actionCollection(),"fullscreen"); #endif mToggleSlideShow=new KToggleAction(i18n("Slide Show..."),"slideshow",0,this,SLOT(toggleSlideShow()),actionCollection(),"slideshow"); mToggleDirAndFileViews=new KAction(i18n("Hide Folder && File Views"),CTRL + Key_Return,this,SLOT(toggleDirAndFileViews()),actionCollection(),"toggle_dir_and_file_views"); // Go mGoUp=new KToolBarPopupAction(i18n("Up"), "up", ALT + Key_Up, this, SLOT(goUp()), actionCollection(), "go_up"); mOpenHomeDir=KStdAction::home(this, SLOT(openHomeDir()), actionCollection() ); // Bookmarks QString file = locate( "data", "kfile/bookmarks.xml" ); if (file.isEmpty()) { file = locateLocal( "data", "kfile/bookmarks.xml" ); } KBookmarkManager* manager=KBookmarkManager::managerForFile(file,false); manager->setUpdate(true); manager->setShowNSBookmarks(false); GVBookmarkOwner* bookmarkOwner=new GVBookmarkOwner(this); KActionMenu* bookmark=new KActionMenu(i18n( "&Bookmarks" ), "bookmark", actionCollection(), "bookmarks" ); new KBookmarkMenu(manager, bookmarkOwner, bookmark->popupMenu(), this->actionCollection(), true); connect(bookmarkOwner,SIGNAL(openURL(const KURL&)), mGVPixmap,SLOT(setDirURL(const KURL&)) ); - connect(mGVPixmap,SIGNAL(urlChanged(const KURL&,const QString&)), + connect(mGVPixmap,SIGNAL(loaded(const KURL&,const QString&)), bookmarkOwner,SLOT(setURL(const KURL&)) ); // Settings mShowConfigDialog= KStdAction::preferences(this, SLOT(showConfigDialog()), actionCollection() ); mShowKeyDialog= KStdAction::keyBindings(this, SLOT(showKeyDialog()), actionCollection() ); (void)new KAction(i18n("Configure External Tools..."), "configure", this, SLOT(showExternalToolDialog()), actionCollection(), "configure_tools"); (void)KStdAction::configureToolbars( this, SLOT(showToolBarDialog()), actionCollection() ); actionCollection()->readShortcutSettings(); } void GVMainWindow::createHideShowAction(KDockWidget* dock) { QString caption; if (dock->mayBeHide()) { caption=i18n("Hide %1").arg(dock->caption()); } else { caption=i18n("Show %1").arg(dock->caption()); } KAction* action=new KAction(caption, 0, dock, SLOT(changeHideShowState()), (QObject*)0 ); if (dock->icon()) { action->setIconSet( QIconSet(*dock->icon()) ); } mWindowListActions.append(action); } void GVMainWindow::updateWindowActions() { QString caption; if (mFolderDock->mayBeHide() || mFileDock->mayBeHide()) { caption=i18n("Hide Folder && File Views"); } else { caption=i18n("Show Folder && File Views"); } mToggleDirAndFileViews->setText(caption); unplugActionList("winlist"); mWindowListActions.clear(); createHideShowAction(mFolderDock); createHideShowAction(mFileDock); createHideShowAction(mPixmapDock); createHideShowAction(mMetaDock); plugActionList("winlist", mWindowListActions); } void GVMainWindow::createConnections() { connect(mGoUp->popupMenu(), SIGNAL(activated(int)), this,SLOT(goUpTo(int))); // Dir view connections connect(mDirView,SIGNAL(dirURLChanged(const KURL&)), mGVPixmap,SLOT(setDirURL(const KURL&)) ); connect(mDirView, SIGNAL(dirRenamed(const KURL&, const KURL&)), this, SLOT(slotDirRenamed(const KURL&, const KURL&)) ); // Pixmap view connections connect(mPixmapView,SIGNAL(selectPrevious()), mFileViewStack,SLOT(slotSelectPrevious()) ); connect(mPixmapView,SIGNAL(selectNext()), mFileViewStack,SLOT(slotSelectNext()) ); connect(mPixmapView,SIGNAL(zoomChanged(double)), this,SLOT(updateFileInfo()) ); // Thumbnail view connections connect(mFileViewStack,SIGNAL(updateStarted(int)), this,SLOT(thumbnailUpdateStarted(int)) ); connect(mFileViewStack,SIGNAL(updateEnded()), this,SLOT(thumbnailUpdateEnded()) ); connect(mFileViewStack,SIGNAL(updatedOneThumbnail()), this,SLOT(thumbnailUpdateProcessedOne()) ); // File view connections connect(mFileViewStack,SIGNAL(urlChanged(const KURL&)), mGVPixmap,SLOT(setURL(const KURL&)) ); connect(mFileViewStack,SIGNAL(completed()), this,SLOT(updateStatusInfo()) ); connect(mFileViewStack,SIGNAL(canceled()), this,SLOT(updateStatusInfo()) ); - // Don't connect mGVPixmap::urlChanged to mDirView. mDirView will be + // Don't connect mGVPixmap::loaded to mDirView. mDirView will be // updated _after_ the file view is done, since it's less important to the // user connect(mFileViewStack,SIGNAL(completedURLListing(const KURL&)), mDirView,SLOT(setURL(const KURL&)) ); // GVPixmap connections connect(mGVPixmap,SIGNAL(loading()), this,SLOT(pixmapLoading()) ); - connect(mGVPixmap,SIGNAL(urlChanged(const KURL&,const QString&)), + connect(mGVPixmap,SIGNAL(loaded(const KURL&,const QString&)), this,SLOT(setURL(const KURL&,const QString&)) ); - connect(mGVPixmap,SIGNAL(urlChanged(const KURL&,const QString&)), + connect(mGVPixmap,SIGNAL(loaded(const KURL&,const QString&)), mFileViewStack,SLOT(setURL(const KURL&,const QString&)) ); connect(mGVPixmap,SIGNAL(saved(const KURL&)), mFileViewStack,SLOT(updateThumbnail(const KURL&)) ); // Slide show connect(mSlideShow,SIGNAL(finished()), mToggleSlideShow,SLOT(activate()) ); // Location bar connect(mURLEdit,SIGNAL(returnPressed(const QString &)), this,SLOT(slotURLEditChanged(const QString &))); // Non configurable stop-fullscreen accel QAccel* accel=new QAccel(this); accel->connectItem(accel->insertItem(Key_Escape),this,SLOT(escapePressed())); // Dock related connect(manager(), SIGNAL(change()), this, SLOT(updateWindowActions()) ); } void GVMainWindow::createLocationToolBar() { // URL Combo mURLEdit=new KHistoryCombo(this); mURLEdit->setDuplicatesEnabled(false); mURLEditCompletion=new KURLCompletion(KURLCompletion::DirCompletion); mURLEditCompletion->setDir("/"); mURLEdit->setCompletionObject(mURLEditCompletion); mURLEdit->setAutoDeleteCompletionObject(true); mURLEdit->setEditText(QDir::current().absPath()); mURLEdit->addToHistory(QDir::current().absPath()); mURLEdit->setDuplicatesEnabled(false); KWidgetAction* comboAction=new KWidgetAction( mURLEdit, i18n("Location Bar"), 0, 0, 0, actionCollection(), "location_url"); comboAction->setShortcutConfigurable(false); comboAction->setAutoSized(true); // Clear button (void)new KAction( i18n("Clear location bar"), QApplication::reverseLayout()?"clear_left" : "locationbar_erase", 0, mURLEdit, SLOT(clearEdit()), actionCollection(), "clear_location"); // URL Label /* we use "kde toolbar widget" to avoid the flat background (looks bad with * styles like Keramik). See konq_misc.cc. */ QLabel* urlLabel=new QLabel(i18n("L&ocation:"), this, "kde toolbar widget"); (void)new KWidgetAction( urlLabel, i18n("L&ocation: "), 0, 0, 0, actionCollection(), "location_label"); urlLabel->setBuddy(mURLEdit); // Go button (void)new KAction(i18n("Go"), "key_enter", 0, this, SLOT(slotGo()), actionCollection(), "location_go"); } //----------------------------------------------------------------------- // // Properties // //----------------------------------------------------------------------- void GVMainWindow::setShowMenuBarInFullScreen(bool value) { mShowMenuBarInFullScreen=value; if (!mToggleFullScreen->isChecked()) return; if (value) { menuBar()->show(); } else { menuBar()->hide(); } } void GVMainWindow::setShowToolBarInFullScreen(bool value) { mShowToolBarInFullScreen=value; if (!mToggleFullScreen->isChecked()) return; if (value) { showToolBars(); } else { hideToolBars(); } } void GVMainWindow::setShowStatusBarInFullScreen(bool value) { mShowStatusBarInFullScreen=value; if (!mToggleFullScreen->isChecked()) return; if (value) { statusBar()->show(); } else { statusBar()->hide(); } } //----------------------------------------------------------------------- // // Configuration // //----------------------------------------------------------------------- void GVMainWindow::readConfig(KConfig* config,const QString& group) { config->setGroup(group); mShowMenuBarInFullScreen=config->readBoolEntry(CONFIG_MENUBAR_IN_FS,false); mShowToolBarInFullScreen=config->readBoolEntry(CONFIG_TOOLBAR_IN_FS,true); mShowStatusBarInFullScreen=config->readBoolEntry(CONFIG_STATUSBAR_IN_FS,false); } void GVMainWindow::writeConfig(KConfig* config,const QString& group) const { config->setGroup(group); config->writeEntry(CONFIG_MENUBAR_IN_FS,mShowMenuBarInFullScreen); config->writeEntry(CONFIG_TOOLBAR_IN_FS,mShowToolBarInFullScreen); config->writeEntry(CONFIG_STATUSBAR_IN_FS,mShowStatusBarInFullScreen); } Index: trunk/kdeextragear-1/gwenview/src/gvhistory.cpp =================================================================== --- trunk/kdeextragear-1/gwenview/src/gvhistory.cpp (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gvhistory.cpp (revision 263335) @@ -1,137 +1,137 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab /* Gwenview - A simple image viewer for KDE Copyright 2000-2003 Aurélien Gâteau Copyright 2003 Tudor Calin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // KDE #include #include #include #include // Local #include "gvpixmap.h" #include "gvhistory.moc" #if KDE_VERSION < 306 #define SAME_URL(u1,u2,slash) u1.cmp(u2,slash) #else #define SAME_URL(u1,u2,slash) u1.equals(u2,slash) #endif const unsigned int MAX_HISTORY_SIZE=12; GVHistory::GVHistory(GVPixmap* gvPixmap, KActionCollection* actionCollection) { mGVPixmap=gvPixmap; mPosition=mHistoryList.end(); mMovingInHistory=false; // Actions mGoBack=new KToolBarPopupAction(i18n("Back"), "back", ALT + Key_Left, this, SLOT(goBack()), actionCollection, "go_back"); mGoForward=new KToolBarPopupAction(i18n("Forward"), "forward", ALT + Key_Right, this, SLOT(goForward()), actionCollection, "go_forward"); // Connections connect(mGoBack->popupMenu(),SIGNAL(activated(int)), this,SLOT(goBackTo(int)) ); connect(mGoForward->popupMenu(),SIGNAL(activated(int)), this,SLOT(goForwardTo(int)) ); connect(mGoBack->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(fillGoBackMenu()) ); connect(mGoForward->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(fillGoForwardMenu()) ); - connect(mGVPixmap, SIGNAL(urlChanged(const KURL&,const QString&) ), + connect(mGVPixmap, SIGNAL(loaded(const KURL&,const QString&) ), this, SLOT(updateHistoryList(const KURL&)) ); } GVHistory::~GVHistory() { } void GVHistory::updateHistoryList(const KURL& url) { if (!mMovingInHistory) { if (mPosition!=mHistoryList.end() && SAME_URL(url, *mPosition, true)) return; // Drop everything after current HistoryList::iterator it=mPosition; ++it; mHistoryList.erase(it, mHistoryList.end()); mHistoryList.append(url); if(mHistoryList.count()==MAX_HISTORY_SIZE) mHistoryList.pop_front(); mPosition=mHistoryList.fromLast(); } mGoBack->setEnabled(mPosition!=mHistoryList.begin()); mGoForward->setEnabled(mPosition!=mHistoryList.fromLast()); } void GVHistory::fillGoBackMenu() { QPopupMenu* menu=mGoBack->popupMenu(); menu->clear(); HistoryList::ConstIterator it; int pos=1; for(it=mHistoryList.begin(); it!=mPosition; ++it, ++pos) { menu->insertItem( (*it).prettyURL(-1), pos, 0); } } void GVHistory::fillGoForwardMenu() { QPopupMenu* menu=mGoForward->popupMenu(); menu->clear(); HistoryList::ConstIterator it=mPosition; ++it; int pos=1; for(; it!=mHistoryList.end(); ++it, ++pos) { menu->insertItem( (*it).prettyURL(-1), pos, -1); } } void GVHistory::goBack() { goBackTo(1); } void GVHistory::goForward() { goForwardTo(1); } void GVHistory::goBackTo(int id) { for (;id>0; --id) --mPosition; mMovingInHistory=true; mGVPixmap->setDirURL(*mPosition); mMovingInHistory=false; } void GVHistory::goForwardTo(int id) { for (;id>0; --id) ++mPosition; mMovingInHistory=true; mGVPixmap->setDirURL(*mPosition); mMovingInHistory=false; } Index: trunk/kdeextragear-1/gwenview/src/gvpixmap.h =================================================================== --- trunk/kdeextragear-1/gwenview/src/gvpixmap.h (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gvpixmap.h (revision 263335) @@ -1,123 +1,124 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab /* Gwenview - A simple image viewer for KDE Copyright (c) 2000-2003 Aurélien Gâteau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GVPIXMAP_H #define GVPIXMAP_H // Qt includes #include #include #include // KDE includes #include #include /** * A pixmap class with zooming capacities * Emits a signal when it changes */ class GVPixmap : public QObject { Q_OBJECT public: enum ModifiedBehavior { Ask=0, SaveSilently=1, DiscardChanges=2 }; GVPixmap(QObject*); ~GVPixmap(); // Properties const QImage& image() const { return mImage; } KURL url() const; const KURL& dirURL() const { return mDirURL; } const QString& filename() const { return mFilename; } int width() const { return mImage.width(); } int height() const { return mImage.height(); } bool isNull() const { return mImage.isNull(); } const QString& imageFormat() const { return mImageFormat; } void setModifiedBehavior(ModifiedBehavior); ModifiedBehavior modifiedBehavior() const; public slots: void setURL(const KURL&); void setDirURL(const KURL&); void setFilename(const QString&); + void reload(); /** * Save to the current file. * Returns false if failed. */ bool save(); void saveAs(); /** print the selected file */ void print(KPrinter *pPrinter); /** * If the image has been modified, prompt the user to save the changes. * Returns true if it's safe to switch to another image. */ bool saveIfModified(); // "Image manipulation" void rotateLeft(); void rotateRight(); void mirror(); void flip(); signals: /** * Emitted when the class starts to load the image. */ void loading(); /** * Emitted when the class has finished loading the image. * Also emitted if the image could not be loaded. */ - void urlChanged(const KURL& dirURL,const QString& filename); + void loaded(const KURL& dirURL,const QString& filename); /** - * Emitted when the image is modified. + * Emitted when the image has been modified. */ void modified(); /** * Emitted when the image has been saved on disk. */ void saved(const KURL& url); private: QImage mImage; KURL mDirURL; QString mFilename; QString mImageFormat; bool mModified; // Store compressed data. Usefull for lossless manipulations. QByteArray mCompressedData; void reset(); void load(); bool saveInternal(const KURL&,const QString& format); }; #endif Index: trunk/kdeextragear-1/gwenview/src/gvpixmap.cpp =================================================================== --- trunk/kdeextragear-1/gwenview/src/gvpixmap.cpp (revision 263334) +++ trunk/kdeextragear-1/gwenview/src/gvpixmap.cpp (revision 263335) @@ -1,386 +1,393 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab /* Gwenview - A simple image viewer for KDE Copyright 2000-2003 Aurélien Gâteau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include // For S_ISDIR // Qt includes #include #include #include // KDE includes #include #include #include #include #include #include #include // Our includes #include #include #include #include const char* CONFIG_SAVE_AUTOMATICALLY="save automatically"; const char* CONFIG_NOTIFICATION_MESSAGES_GROUP="Notification Messages"; GVPixmap::GVPixmap(QObject* parent) : QObject(parent) , mModified(false) {} GVPixmap::~GVPixmap() { } void GVPixmap::setURL(const KURL& paramURL) { //kdDebug() << "GVPixmap::setURL " << paramURL.prettyURL() << endl; KURL URL(paramURL); if (URL.cmp(url())) return; // Ask to save if necessary. if (!saveIfModified()) { - emit urlChanged(mDirURL,mFilename); + // Not saved, notify others that we stay on the image + emit loaded(mDirURL,mFilename); return; } if (URL.isEmpty()) { reset(); return; } // Fix wrong protocol if (GVArchive::protocolIsArchive(URL.protocol())) { QFileInfo info(URL.path()); if (info.exists()) { URL.setProtocol("file"); } } // Check whether this is a dir or a file KIO::UDSEntry entry; bool isDir=false; if (!KIO::NetAccess::stat(URL,entry)) return; KIO::UDSEntry::ConstIterator it; for(it=entry.begin();it!=entry.end();++it) { if ((*it).m_uds==KIO::UDS_FILE_TYPE) { isDir=S_ISDIR( (*it).m_long ); break; } } if (isDir) { mDirURL=URL; mFilename=""; } else { mDirURL=URL.upURL(); mFilename=URL.filename(); } if (mFilename.isEmpty()) { reset(); return; } - emit loading(); load(); - emit urlChanged(mDirURL,mFilename); } void GVPixmap::setDirURL(const KURL& paramURL) { if (!saveIfModified()) { - emit urlChanged(mDirURL,mFilename); + emit loaded(mDirURL,mFilename); return; } mDirURL=paramURL; mFilename=""; reset(); } void GVPixmap::setFilename(const QString& filename) { if (mFilename==filename) return; if (!saveIfModified()) { - emit urlChanged(mDirURL,mFilename); + emit loaded(mDirURL,mFilename); return; } mFilename=filename; - emit loading(); load(); - emit urlChanged(mDirURL,mFilename); } -void GVPixmap::print(KPrinter *pPrinter) -{ + +void GVPixmap::reload() { + load(); + // FIXME: Ugly, use another signal or rename this one + emit saved(url()); +} + + +void GVPixmap::print(KPrinter *pPrinter) { QPainter printpainter; // Is this needed? KURL url = this->url(); QString path=url.path(); pPrinter->setDocName(mFilename); printpainter.begin(pPrinter); printpainter.drawImage(0,0,mImage); printpainter.end(); } KURL GVPixmap::url() const { KURL url=mDirURL; url.addPath(mFilename); return url; } void GVPixmap::rotateLeft() { // Apply the rotation to the compressed data too if available if (mImageFormat=="JPEG" && !mCompressedData.isNull()) { mCompressedData=GVJPEGTran::apply(mCompressedData,GVImageUtils::Rot270); } QWMatrix matrix; matrix.rotate(-90); mImage=mImage.xForm(matrix); mModified=true; emit modified(); } void GVPixmap::rotateRight() { if (mImageFormat=="JPEG" && !mCompressedData.isNull()) { mCompressedData=GVJPEGTran::apply(mCompressedData,GVImageUtils::Rot90); } QWMatrix matrix; matrix.rotate(90); mImage=mImage.xForm(matrix); mModified=true; emit modified(); } void GVPixmap::mirror() { if (mImageFormat=="JPEG" && !mCompressedData.isNull()) { mCompressedData=GVJPEGTran::apply(mCompressedData,GVImageUtils::HFlip); } QWMatrix matrix; matrix.scale(-1,1); mImage=mImage.xForm(matrix); mModified=true; emit modified(); } void GVPixmap::flip() { if (mImageFormat=="JPEG" && !mCompressedData.isNull()) { mCompressedData=GVJPEGTran::apply(mCompressedData,GVImageUtils::VFlip); } QWMatrix matrix; matrix.scale(1,-1); mImage=mImage.xForm(matrix); mModified=true; emit modified(); } bool GVPixmap::save() { if (!saveInternal(url(),mImageFormat)) { KMessageBox::sorry(0,i18n("Could not save file.")); return false; } return true; } void GVPixmap::saveAs() { QString format=mImageFormat; KURL saveURL; if (url().isLocalFile()) saveURL=url(); GVImageSaveDialog dialog(saveURL,format,0); if (!dialog.exec()) return; if (!saveInternal(saveURL,format)) { KMessageBox::sorry(0,i18n("Could not save file.")); } } bool GVPixmap::saveIfModified() { if (!mModified) return true; QString msg=i18n("The image %1 has been modified, do you want to save the changes?") .arg(url().prettyURL()); int result=KMessageBox::questionYesNoCancel(0, msg, QString::null, i18n("Save"), i18n("Discard"), CONFIG_SAVE_AUTOMATICALLY); switch (result) { case KMessageBox::Yes: return save(); case KMessageBox::No: mModified=false; return true; default: return false; } } //--------------------------------------------------------------------- // // Config // //--------------------------------------------------------------------- static GVPixmap::ModifiedBehavior stringToModifiedBehavior(const QString& str) { if (str=="yes") return GVPixmap::SaveSilently; if (str=="no") return GVPixmap::DiscardChanges; return GVPixmap::Ask; } static QString modifiedBehaviorToString(GVPixmap::ModifiedBehavior behaviour) { if (behaviour==GVPixmap::SaveSilently) return "yes"; if (behaviour==GVPixmap::DiscardChanges) return "no"; return ""; } void GVPixmap::setModifiedBehavior(ModifiedBehavior value) { KConfig* config=KGlobal::config(); KConfigGroupSaver saver(config, CONFIG_NOTIFICATION_MESSAGES_GROUP); config->setGroup(CONFIG_NOTIFICATION_MESSAGES_GROUP); config->writeEntry(CONFIG_SAVE_AUTOMATICALLY, modifiedBehaviorToString(value)); } GVPixmap::ModifiedBehavior GVPixmap::modifiedBehavior() const { KConfig* config=KGlobal::config(); KConfigGroupSaver saver(config, CONFIG_NOTIFICATION_MESSAGES_GROUP); QString str=config->readEntry(CONFIG_SAVE_AUTOMATICALLY); return stringToModifiedBehavior(str.lower()); } //--------------------------------------------------------------------- // // Private stuff // //--------------------------------------------------------------------- void GVPixmap::load() { + emit loading(); KURL pixURL=url(); + Q_ASSERT(!pixURL.isEmpty()); //kdDebug() << "GVPixmap::load() " << pixURL.prettyURL() << endl; QString path; if (!KIO::NetAccess::download(pixURL,path)) { mImage.reset(); + emit loaded(mDirURL,""); return; } // Load file. We load it ourself so that we can keep a copy of the // compressed data. This is used by JPEG lossless manipulations. QFile file(path); file.open(IO_ReadOnly); QDataStream stream(&file); mCompressedData.resize(file.size()); stream.readRawBytes(mCompressedData.data(),mCompressedData.size()); // Decode image mImageFormat=QString(QImage::imageFormat(path)); if (mImage.loadFromData(mCompressedData,mImageFormat.ascii())) { // Convert depth if necessary // (32 bit depth is necessary for alpha-blending) if (mImage.depth()<32 && mImage.hasAlphaBuffer()) { mImage=mImage.convertDepth(32); } // If the image is a JPEG, rotate the decode image and the compressed // data if necessary, otherwise throw the compressed data away if (mImageFormat=="JPEG") { GVImageUtils::Orientation orientation=GVImageUtils::getOrientation(mCompressedData); if (orientation!=GVImageUtils::NotAvailable && orientation!=GVImageUtils::Normal) { mImage=GVImageUtils::rotate(mImage, orientation); mCompressedData=GVJPEGTran::apply(mCompressedData,orientation); mCompressedData=GVImageUtils::setOrientation(mCompressedData,GVImageUtils::Normal); } } else { mCompressedData.resize(0); } } else { mImage.reset(); } - KIO::NetAccess::removeTempFile(path); + emit loaded(mDirURL,mFilename); } bool GVPixmap::saveInternal(const KURL& url, const QString& format) { bool result; KTempFile tmp; tmp.setAutoDelete(true); QString path; if (url.isLocalFile()) { path=url.path(); } else { path=tmp.name(); } if (format=="JPEG" && !mCompressedData.isNull()) { //kdDebug() << "Lossless save\n"; QFile file(path); result=file.open(IO_WriteOnly); if (!result) return false; QDataStream stream(&file); stream.writeRawBytes(mCompressedData.data(),mCompressedData.size()); } else { result=mImage.save(path,format.ascii()); if (!result) return false; } if (!url.isLocalFile()) { result=KIO::NetAccess::upload(tmp.name(),url); } if (result) { emit saved(url); mModified=false; } return result; } void GVPixmap::reset() { mImage.reset(); mCompressedData.resize(0); - emit urlChanged(mDirURL,mFilename); + emit loaded(mDirURL,mFilename); } Index: trunk/kdeextragear-1/gwenview/NEWS =================================================================== --- trunk/kdeextragear-1/gwenview/NEWS (revision 263334) +++ trunk/kdeextragear-1/gwenview/NEWS (revision 263335) @@ -1,389 +1,390 @@ 2003.xx.xx - v1.0.0pre3 - New features: - - Added a "Go" button to the location toolbar. - Gwenview can now silently save or discard changes when leaving a modified image. + - Added a reload button. + - Added a "Go" button to the location toolbar. - Fixes: - Really fixed saving of external tools. - Make sure the folder view is updated when a folder is renamed. - The mouse-wheel behaviors are not messed anymore by dialogs or by showing the popup menu. 2003.10.11 - v1.0.0pre2 - New features: - Added Back/Forward history buttons (based on work from Tudor Calin). - The parent button can now display a popup menu (by Tudor Calin). - Simple printing support (by Angelo Naselli). - Fixes: - The image comment editor shows more explicit messages when the comment is empty and when the image can't be commented. - The external tool dialog won't fail on fresh installation. - The path to jpegtran is now stored correctly, even if it's not absolute. - Fixed compilation failure on KDE 3.0. 2003.09.27 - v1.0.0pre1 - New features: - Toolbars are now configurable and toolbar settings are remembered. - New dock window to display Meta Info (thanks to Jos van den Oever). - Cursor over image view changes to reflect the current behavior. - When toggling autozoom off, restore the previous zoom and position (Based on a patch by Jos van den Oever). - It's now possible to define external tools associated with images or directories. - Fixes: - Exiting with Ctrl+Q from the fullscreen won't close the file view for the next startup. - Do not switch the file view to detailed mode when leaving the fullscreen mode. - Do not stop displaying images when browsing folders containing lots of JPEG files (more than a thousand). 2003.06.09 - v0.17.1a - Fixes: - Fixed compilation failure on KDE 3.0. 2003.03.29 - v0.17.1 - Fixes: - In the folder view, show the "+" sign in front of folders if they have sub-folders. - Lossless manipulations of JPEG images won't remove the EXIF information anymore. - Handling of the EXIF orientation tag should now work on KDE 3.0. - When "auto-zoom" was on, pressing the "reset zoom" button would not disactivate it. - Added an "Edit" submenu to the popup menu of the image view, similar to the main window "Edit" menu. - Moved "Open with editor" in the "Edit" menu. - Display the image file name in the window title. - Fixed the bug which caused the window to grow up when entering folders with long names (Thanks to Stefan Heinze for the tip). - Rotating big JPEG images with JPEGTran won't hang anymore. - Keep the fullscreen button activated to be able to go back to normal mode when moving to a dir without images in fullscreen mode. 2003.05.04 - v0.17.0 - New features: - Added a cancel button to popup menus, like Konqueror does. - Added support for dropping files to the file view. - Fixes: - Fixed compilation failure on KDE 3.0. - Clear the image view when the last image of the current folder is removed. - Hopefully fixed the bug which caused Gwenview to sometimes crash when invoked with a folder in the command line. 2003.04.27 - v0.17.0pre3 - Fixes: - Really fixed the bug which caused the dock layout to be messed after going fullscreen. - Always display the location bar on a new line. - Fixed the lock which could occur if you kept the go-to-previous or go-to-next shortcut keys pressed for too long. 2003.04.26 - v0.17.0pre2 - New features: - Support for EXIF orientation information. - Fixes: - Don't alter the layout of the docks when toggling dir and file views or going fullscreen. - File name won't be cut anymore in the thumbnail view. - Prompt to save a modified image before quitting. - Fixed an inconsistency with JPEG lossless rotation. 2003.04.21 - v0.17.0pre1 - New features: - Added bookmarks. - Show/hide hidden files. - Image rotation and mirroring (using jpegtran when working on JPEG files to perform lossless manipulations). - Image saving. - You can now smooth scale images. - New entry in the "View" menu: "Hide Folder And File Views". - New option to enlarge smaller images when using auto zoom. - New option to toggle scroll bars on image view. - New option to select whether deleting files should send them to the trash or not. - Fixes: - Moved the slide show settings to a separate dialog shown before starting it. - Image count in the status bar doesn't include archives anymore. - Do not zoom the transparency checkerboard. 2003.02.13 - v0.16.2 - Fixes: - Uses opaque resize for docked views. - Resizing the window resizes the image view only. - When using double click mode, double clicking a folder in the icon view did not open the folder. 2003.01.31 - v0.16.1 - Fixes: - Fixed compilation failure with KDE 3.0 (Thanks to GeniusR13). 2003.01.30 - v0.16.0 - New features: - Support for zip IO slave. - Added an "erase url" button. - Fixes: - Corrected toolbar layout for RTL languages (Thanks to Meni Livne). - Do not give focus to the address bar on start. - Do not exit when trying to thumbnailing a broken JPEG (Thanks to Marco Gazzetta). - The previous/next shortcuts were wrong in 0.16.0pre1. 2003.01.12 - v0.16.0pre1 - New features: - Support for IO slaves: you can browse FTP files, Windows shares, go into tarballs... - Multi-selection support (at last!). - Added a "home folder" tree branch to the folder view. - Added a simple slideshow feature. - Now uses the trash to delete images. - Added an address bar. - Displays the filename of the current image in a different (configurable) color. - Fixes: - Do not start dragging folders in the folder view when not necessary. - When dropping urls and selecting "Move", the drop item will become the current one only if the item which was the current one was part of the drop. 2002.11.05 - v0.15.2 - Fixes: - Small jpeg images were getting a stretched thumbnail. - Fixed the centering of image in scrollable view. - Enabled the "show folders in file view" by default. 2002.10.26 - v0.15.1 - New features: - Added an item to the popup menus to show the file properties. - Fixes: - The selected thumbnail does not look strange anymore when changing the thumbnail size. - Always zoom on the center of the image. - Do not reload the image every time when opening the context menu. 2002.10.04 - v0.15.0 - File count was also counting folders. - Integrated the updated man page by Michael Spanier. - Selected thumbnail looks nicer now. - Fixed automatic deselection of the selected thumbnail when using single-click mode. 2002.09.14 - v0.15.0pre1 - New option to prevent Gwenview from loading the first image when it enters a folder (Thanks to Andreas Pfaller for the patch). - You can now show the folders in the file view. By enabling this and hiding the folder view, Gwenview won't have to open all parent folders on startup. - XCF file format support, thanks to the QXCFI library by Lignum Computing (http://lignumcomputing.com). - Thumbnail generator now always saves the thumbnail at the biggest size : for smaller sizes the big thumbnail is loaded and scaled. This uses less disk space and make thumbnail size switching faster. - Reworked the zoom behaviour so that it works like the zoom tool in the GIMP. 2002.08.11 - v0.14.5 - Fixed the horizontal one pixel lines which appeared in fullscreen mode when the toolbar was hidden. - New command line option (-f) to start in fullscreen mode. 2002.07.28 - v0.14.4 - Updated thumbnail generation to store thumbnails in the same folder Konqueror 3 uses (Thanks to Andreas Pfaller and Renchi Raju for the patches). - Fixed a crash on exit under certain circumstances. - Should not crash anymore when loading big images. 2002.07.15 - v0.14.3 - Really fixed the bug which caused Gwenview to not display image file given as an argument. - Fixed ugly look of file names in thumbnail view when word wrap was enabled. - Fixed flickering and drawing artefacts remaining after zooming in and out. - Lock zoom state was not properly remembered. - Updated polish translation. - Updated german translation. 2002.07.10 - v0.14.2 - Fixed a crash if a directory contained URL-like encoded characters (Thanks to Dario Abatianni for the bug report) - Do not reload all thumbnails if an image is removed. - When starting Gwenview with an image file as an argument, the image does not hide anymore. - Gwenview won't crash anymore if started with a file that doesn't exist as an argument. 2002.06.17 - v0.14.1 - Fixed a bug in recognition of progressive jpeg images. - Updated swedish translation by Anders Lindén. - Added a japanese translation by Ryota Simamoto. 2002.06.15 - v0.14.0 - Ported to KDE3 - Gwenview uses KImageIO for file formats, bringing a few other file formats such as ico, eps or g3. - Replaced my own dir widget with the new KDirView widget provided by KDE3. 2002.05.04 - v0.13.0 - Thumbnail selection buttons are always activated. - You can now choose between 'auto-zoom' or 'scroll-and-zoom' in fullscreen mode. - You can now lock the zoom to keep the same zoom value during browsing. - Integrated a patch from Frank Becker to speed up JPEG thumbnail generation. - Swedish translation. - More personalizable wheel behaviour. - Gwenview now remembers the 'auto-zoom' state. - You can now define what interface elements you want to hide in fullscreen mode. - Fixed a bug in cache cleaning if the cache was already empty. 2002.03.04 - v0.12.0 - Navigation buttons are now enabled or disabled according to the position of the file in the folder. - New zoom option : fit to window. - Zoom actions are disabled when there's no image. - No more ugly thumbnails when selected. - Images are now centered in main view. - Added popup menus to the file and image views. - Thumbnails aren't reloaded anymore when deleting a file. - Added support for external editor. 2001.12.30 - v0.11.1 - Added TIFF support. - Added drag'n drop support to folder view. - Bug fix when renaming folder containing folders. 2001.12.15 - v0.11.0 - Korean translation. - New folder view : more responsive, get automatically updated on changes, features a popup menu. - Scrollbars are now reset on image change. - Should now installs itself in /Graphics rather than in /Multimedia/Graphics. - New buttons in config dialog to get the cache size and to empty it. - Added a man page by Michael Spanier. 2001.10.11 - v0.10.1 - Dutch translation. - Hungarian translation. - Now uses Konqueror central thumbnail cache folder. 2001.09.29 - v0.10.0 - Italian translation. - Polish translation. - Redesigned the configuration dialog with Qt-Designer, now features GUI for Avinash Chopde's patch. - Added a file/open menu item. - Added an option to hide file names in fullscreen mode. - Gwenview now displays an error message when it can't load an image. 2001.09.01 - v0.9.2 - German translation. - Fixed a bug which caused the fullscreen view to be updated even after coming back to normal. - Merged a patch from Avinash Chopde to provide default folders for file copy/move and bypass file operation confirmations (No GUI yet). 2001.08.29 - v0.9.1 - Spanish translation. - Fixed bad encoding in French translation (no more '?' instead of accent). - Dock icons were too big. Fixed. 2001.08.20 - v0.9.0 - Added support for alpha channel. - Gwenview now displays the image size in status bar. - Fixed wrong icon size for folders on some distributions (my mistake). 2001.07.30 - v0.8.0 - Replaced thumbnail generation with Konqueror code : don't freeze the interface anymore and cache generated thumbnails on disk. - You can now select the size of the thumbnails from the menu/toolbar. 2001.07.11 - v0.7.0 - Added zoom in and out feature. - Thumbnail generation is now non-blocking. - Uses KIO for file operations. - Added "move" to file operations. - Selecting a folder which does not contain images will now empty the image widget. - Added a status bar displaying folder and file information. - Opera-like previous-next mouse navigation. - Scroll the image by dragging it. - Fixed a bug which could prevent the toolbar from showing on the first launch. 2001.05.23 - v0.6.1 - Fixed a bug in file view that might not display files. - Added a Norwegian translation, thanks to Rune Nordvik. 2001.05.16 - v0.6.0 - Full screen support with keyboard, mouse button and mouse wheel navigation. - Added a toolbar. - Folder view uses standard folder icons. - Integration with Konqueror : right click on any folder and select "Browse with Gwenview". 2001.04.10 - v0.5.1 - Fixed drag'n'drop for file detail view. 2001.03.31 - v0.5.0 - File view items can now be dragged to any KDE application (for example Konqueror). - French translation. - File copy dialog opens in current folder. - Fixed a bug on file copy cancel. - Fixed a crash on file deletion. - Shortcut keys are now configurable. - When using thumbnail view, files are all shown before thumbnail generation begins. - Added a configuration dialog. 2001.03.09 - v0.4.1 - Fixed crash on file manipulation using thumbnail view. - Added a progress gauge for thumbnail generation. 2001.02.26 - v0.4.0 - File list use a standard KDE detail view. - Added a configurable memory cache to speed up image loading. 2001.01.28 - v0.3.0 - Nicer window menu. - Removed FilePath module : use QT instead. - Some code cleaning. - New shortcut for first/previous/next/last image. - Icon for folders. - Removed folder column header. - Thumbnail view. 2001.01.16 - v0.2.2 - Added a window menu to toggle visibility of windows. - Changed the default button in delete dialog to "Yes". 2001.01.15 - v0.2.1 - Updated mail address and web site. 2001.01.08 - v0.2.0 - Uses docked windows. - Remember window sizes and configurations. - Added Help menu with about dialog. - Uses the KDE way to handle command line parameters. - Added ability to copy a file. 2000.12.10 - v0.1.0 - Initial release.