Warning, file /office/calligra/libs/main/KoView.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 0003 Copyright (C) 2007 Thomas Zander <zander@kde.org> 0004 Copyright (C) 2010 Benjamin Port <port.benjamin@gmail.com> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KoView.h" 0023 0024 // local directory 0025 #include "KoView_p.h" 0026 0027 #include "KoPart.h" 0028 #include "KoDockRegistry.h" 0029 #include "KoDocument.h" 0030 #include "KoMainWindow.h" 0031 0032 #ifndef QT_NO_DBUS 0033 #include "KoViewAdaptor.h" 0034 #include <QDBusConnection> 0035 #endif 0036 0037 #include "KoDockFactoryBase.h" 0038 #include "KoUndoStackAction.h" 0039 #include "KoGlobal.h" 0040 #include "KoPageLayout.h" 0041 #include "KoPrintJob.h" 0042 #include "KoDocumentInfo.h" 0043 0044 #include <KoIcon.h> 0045 0046 #include <kactioncollection.h> 0047 #include <klocalizedstring.h> 0048 #include <MainDebug.h> 0049 #include <kmessagebox.h> 0050 #include <KoNetAccess.h> 0051 #include <kselectaction.h> 0052 #include <kconfiggroup.h> 0053 #include <KSharedConfig> 0054 0055 #include <QStatusBar> 0056 #include <QDockWidget> 0057 #include <QApplication> 0058 #include <QList> 0059 #include <QDropEvent> 0060 #include <QDragEnterEvent> 0061 #include <QImage> 0062 #include <QUrl> 0063 #include <QPrintDialog> 0064 0065 //static 0066 QString KoView::newObjectName() 0067 { 0068 static int s_viewIFNumber = 0; 0069 QString name; name.setNum(s_viewIFNumber++); name.prepend("view_"); 0070 return name; 0071 } 0072 0073 0074 class KoViewPrivate 0075 { 0076 public: 0077 KoViewPrivate() { 0078 tempActiveWidget = 0; 0079 documentDeleted = false; 0080 actionAuthor = 0; 0081 } 0082 ~KoViewPrivate() { 0083 } 0084 0085 QPointer<KoDocument> document; // our KoDocument 0086 QPointer<KoPart> part; // our part 0087 QWidget *tempActiveWidget; 0088 bool documentDeleted; // true when document gets deleted [can't use document==0 0089 // since this only happens in ~QObject, and views 0090 // get deleted by ~KoDocument]. 0091 0092 0093 // Hmm sorry for polluting the private class with such a big inner class. 0094 // At the beginning it was a little struct :) 0095 class StatusBarItem 0096 { 0097 public: 0098 StatusBarItem() // for QValueList 0099 : m_widget(0), 0100 m_connected(false), 0101 m_hidden(false) {} 0102 0103 StatusBarItem(QWidget * widget, int stretch, bool permanent) 0104 : m_widget(widget), 0105 m_stretch(stretch), 0106 m_permanent(permanent), 0107 m_connected(false), 0108 m_hidden(false) {} 0109 0110 bool operator==(const StatusBarItem& rhs) { 0111 return m_widget == rhs.m_widget; 0112 } 0113 0114 bool operator!=(const StatusBarItem& rhs) { 0115 return m_widget != rhs.m_widget; 0116 } 0117 0118 QWidget * widget() const { 0119 return m_widget; 0120 } 0121 0122 void ensureItemShown(QStatusBar * sb) { 0123 Q_ASSERT(m_widget); 0124 if (!m_connected) { 0125 if (m_permanent) 0126 sb->addPermanentWidget(m_widget, m_stretch); 0127 else 0128 sb->addWidget(m_widget, m_stretch); 0129 0130 if(!m_hidden) 0131 m_widget->show(); 0132 0133 m_connected = true; 0134 } 0135 } 0136 void ensureItemHidden(QStatusBar * sb) { 0137 if (m_connected) { 0138 m_hidden = m_widget->isHidden(); 0139 sb->removeWidget(m_widget); 0140 m_widget->hide(); 0141 m_connected = false; 0142 } 0143 } 0144 private: 0145 QWidget * m_widget; 0146 int m_stretch; 0147 bool m_permanent; 0148 bool m_connected; 0149 bool m_hidden; 0150 }; 0151 0152 QList<StatusBarItem> statusBarItems; // Our statusbar items 0153 bool inOperation; //in the middle of an operation (no screen refreshing)? 0154 KSelectAction *actionAuthor; // Select action for author profile. 0155 }; 0156 0157 KoView::KoView(KoPart *part, KoDocument *document, QWidget *parent) 0158 : QWidget(parent) 0159 , d(new KoViewPrivate) 0160 { 0161 Q_ASSERT(document); 0162 Q_ASSERT(part); 0163 0164 setObjectName(newObjectName()); 0165 0166 #ifndef QT_NO_DBUS 0167 new KoViewAdaptor(this); 0168 QDBusConnection::sessionBus().registerObject('/' + objectName(), this); 0169 #endif 0170 0171 d->document = document; 0172 d->part = part; 0173 0174 setFocusPolicy(Qt::StrongFocus); 0175 0176 setupGlobalActions(); 0177 0178 QStatusBar * sb = statusBar(); 0179 if (sb) { // No statusbar in e.g. konqueror 0180 connect(d->document, SIGNAL(statusBarMessage(QString)), 0181 this, SLOT(slotActionStatusText(QString))); 0182 connect(d->document, SIGNAL(clearStatusBarMessage()), 0183 this, SLOT(slotClearStatusText())); 0184 } 0185 0186 // add all plugins. 0187 foreach(const QString & docker, KoDockRegistry::instance()->keys()) { 0188 KoDockFactoryBase *factory = KoDockRegistry::instance()->value(docker); 0189 if (mainWindow()) 0190 mainWindow()->createDockWidget(factory); 0191 } 0192 0193 actionCollection()->addAssociatedWidget(this); 0194 0195 /** 0196 * WARNING: This code changes the context of global shortcuts 0197 * only. All actions added later will have the default 0198 * context, which is Qt::WindowShortcut! 0199 */ 0200 foreach(QAction* action, actionCollection()->actions()) { 0201 action->setShortcutContext(Qt::WidgetWithChildrenShortcut); 0202 } 0203 } 0204 0205 KoView::~KoView() 0206 { 0207 if (!d->documentDeleted) { 0208 if (d->document) { 0209 d->part->removeView(this); 0210 } 0211 } 0212 delete d; 0213 } 0214 0215 0216 void KoView::dragEnterEvent(QDragEnterEvent *event) 0217 { 0218 if (event->mimeData()->hasImage() 0219 || event->mimeData()->hasUrls()) { 0220 event->accept(); 0221 } else { 0222 event->ignore(); 0223 } 0224 } 0225 0226 void KoView::dropEvent(QDropEvent *event) 0227 { 0228 // we can drop a list of urls from, for instance dolphin 0229 QVector<QImage> images; 0230 0231 if (event->mimeData()->hasImage()) { 0232 QImage image = event->mimeData()->imageData().value<QImage>(); 0233 if (!image.isNull()) { 0234 // apparently hasImage() && imageData().value<QImage>().isNull() 0235 // can hold sometimes (Qt bug?). 0236 images << image; 0237 } 0238 } 0239 else if (event->mimeData()->hasUrls()) { 0240 QList<QUrl> urls = event->mimeData()->urls(); 0241 foreach (const QUrl &url, urls) { 0242 QImage image; 0243 QUrl kurl(url); 0244 // make sure we download the files before inserting them 0245 if (!kurl.isLocalFile()) { 0246 QString tmpFile; 0247 if( KIO::NetAccess::download(kurl, tmpFile, this)) { 0248 image.load(tmpFile); 0249 KIO::NetAccess::removeTempFile(tmpFile); 0250 } else { 0251 KMessageBox::error(this, KIO::NetAccess::lastErrorString()); 0252 } 0253 } 0254 else { 0255 image.load(kurl.toLocalFile()); 0256 } 0257 if (!image.isNull()) { 0258 images << image; 0259 } 0260 } 0261 } 0262 0263 if (!images.isEmpty()) { 0264 addImages(images, event->pos()); 0265 } 0266 } 0267 0268 0269 void KoView::addImages(const QVector<QImage> &, const QPoint &) 0270 { 0271 // override in your application 0272 } 0273 0274 KoDocument *KoView::koDocument() const 0275 { 0276 return d->document; 0277 } 0278 0279 void KoView::setDocumentDeleted() 0280 { 0281 d->documentDeleted = true; 0282 } 0283 0284 void KoView::addStatusBarItem(QWidget * widget, int stretch, bool permanent) 0285 { 0286 KoViewPrivate::StatusBarItem item(widget, stretch, permanent); 0287 QStatusBar * sb = statusBar(); 0288 if (sb) { 0289 item.ensureItemShown(sb); 0290 } 0291 d->statusBarItems.append(item); 0292 } 0293 0294 void KoView::removeStatusBarItem(QWidget *widget) 0295 { 0296 QStatusBar *sb = statusBar(); 0297 0298 int itemCount = d->statusBarItems.count(); 0299 for (int i = itemCount-1; i >= 0; --i) { 0300 KoViewPrivate::StatusBarItem &sbItem = d->statusBarItems[i]; 0301 if (sbItem.widget() == widget) { 0302 if (sb) { 0303 sbItem.ensureItemHidden(sb); 0304 } 0305 d->statusBarItems.removeOne(sbItem); 0306 break; 0307 } 0308 } 0309 } 0310 0311 KoPrintJob * KoView::createPrintJob() 0312 { 0313 warnMain << "Printing not implemented in this application"; 0314 return 0; 0315 } 0316 0317 KoPrintJob * KoView::createPdfPrintJob() 0318 { 0319 return createPrintJob(); 0320 } 0321 0322 KoPageLayout KoView::pageLayout() const 0323 { 0324 return koDocument()->pageLayout(); 0325 } 0326 0327 QPrintDialog *KoView::createPrintDialog(KoPrintJob *printJob, QWidget *parent) 0328 { 0329 QPrintDialog *printDialog = new QPrintDialog(&printJob->printer(), parent); 0330 printDialog->setOptionTabs(printJob->createOptionWidgets()); 0331 printDialog->setMinMax(printJob->printer().fromPage(), printJob->printer().toPage()); 0332 printDialog->setEnabledOptions(printJob->printDialogOptions()); 0333 return printDialog; 0334 } 0335 0336 void KoView::setupGlobalActions() 0337 { 0338 QAction *undo = actionCollection()->addAction("edit_undo", new KoUndoStackAction(d->document->undoStack(), KoUndoStackAction::UNDO)); 0339 QAction *redo = actionCollection()->addAction("edit_redo", new KoUndoStackAction(d->document->undoStack(), KoUndoStackAction::RED0)); 0340 0341 actionCollection()->setDefaultShortcut(undo, QKeySequence::Undo); 0342 actionCollection()->setDefaultShortcut(redo, QKeySequence::Redo); 0343 d->actionAuthor = new KSelectAction(koIcon("user-identity"), i18n("Active Author Profile"), this); 0344 connect(d->actionAuthor, SIGNAL(triggered(QString)), this, SLOT(changeAuthorProfile(QString))); 0345 actionCollection()->addAction("settings_active_author", d->actionAuthor); 0346 0347 slotUpdateAuthorProfileActions(); 0348 } 0349 0350 void KoView::changeAuthorProfile(const QString &profileName) 0351 { 0352 KConfigGroup appAuthorGroup( KSharedConfig::openConfig(), "Author"); 0353 if (profileName.isEmpty()) { 0354 appAuthorGroup.writeEntry("active-profile", ""); 0355 } else if (profileName == i18nc("choice for author profile", "Anonymous")) { 0356 appAuthorGroup.writeEntry("active-profile", "anonymous"); 0357 } else { 0358 appAuthorGroup.writeEntry("active-profile", profileName); 0359 } 0360 appAuthorGroup.sync(); 0361 d->document->documentInfo()->updateParameters(); 0362 } 0363 0364 KoMainWindow * KoView::mainWindow() const 0365 { 0366 // It is possible (when embedded inside a Gemini window) that you have a KoMainWindow which 0367 // is not the top level window. The code below ensures you can still get access to it, even 0368 // in that case. 0369 KoMainWindow* mw = dynamic_cast<KoMainWindow *>(window()); 0370 QWidget* parent = parentWidget(); 0371 while (!mw) { 0372 mw = dynamic_cast<KoMainWindow*>(parent); 0373 parent = parent->parentWidget(); 0374 if (!parent) { 0375 break; 0376 } 0377 } 0378 return mw; 0379 } 0380 0381 QStatusBar * KoView::statusBar() const 0382 { 0383 KoMainWindow *mw = mainWindow(); 0384 return mw ? mw->statusBar() : 0; 0385 } 0386 0387 void KoView::slotActionStatusText(const QString &text) 0388 { 0389 QStatusBar *sb = statusBar(); 0390 if (sb) 0391 sb->showMessage(text); 0392 } 0393 0394 void KoView::slotClearStatusText() 0395 { 0396 QStatusBar *sb = statusBar(); 0397 if (sb) 0398 sb->clearMessage(); 0399 } 0400 0401 void KoView::slotUpdateAuthorProfileActions() 0402 { 0403 Q_ASSERT(d->actionAuthor); 0404 if (!d->actionAuthor) { 0405 return; 0406 } 0407 d->actionAuthor->clear(); 0408 d->actionAuthor->addAction(i18n("Default Author Profile")); 0409 d->actionAuthor->addAction(i18nc("choice for author profile", "Anonymous")); 0410 0411 KConfigGroup authorGroup(KoGlobal::calligraConfig(), "Author"); 0412 QStringList profiles = authorGroup.readEntry("profile-names", QStringList()); 0413 foreach (const QString &profile , profiles) { 0414 d->actionAuthor->addAction(profile); 0415 } 0416 0417 KConfigGroup appAuthorGroup( KSharedConfig::openConfig(), "Author"); 0418 QString profileName = appAuthorGroup.readEntry("active-profile", ""); 0419 if (profileName == "anonymous") { 0420 d->actionAuthor->setCurrentItem(1); 0421 } else if (profiles.contains(profileName)) { 0422 d->actionAuthor->setCurrentAction(profileName); 0423 } else { 0424 d->actionAuthor->setCurrentItem(0); 0425 } 0426 } 0427 0428 QList<QAction*> KoView::createChangeUnitActions(bool addPixelUnit) 0429 { 0430 UnitActionGroup* unitActions = new UnitActionGroup(d->document, addPixelUnit, this); 0431 return unitActions->actions(); 0432 } 0433 0434 void KoView::guiActivateEvent(bool activated) 0435 { 0436 Q_UNUSED(activated); 0437 }