Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / konqueror / src / konqmainwindow.cpp
blobe6e41bae2ad3cbfd2ed6b4b9c0ffea8a438944dd
1 /* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Simon Hausmann <hausmann@kde.org>
3 Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
4 Copyright (C) 2000-2005 David Faure <faure@kde.org>
5 Copyright (C) 2007 Eduardo Robles Elvira <edulix@gmail.com>
6 Copyright (C) 2007 Daniel GarcĂ­a Moreno <danigm@gmail.com>
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
24 #include "konqmainwindow.h"
25 #include "konqclosedwindowsmanager.h"
26 #include "konqsessionmanager.h"
27 #include "konqsessiondlg.h"
28 #include "konqdraggablelabel.h"
29 #include "konqcloseditem.h"
30 #include "konqapplication.h"
31 #include "konqguiclients.h"
32 #include "KonqMainWindowAdaptor.h"
33 #include "KonquerorAdaptor.h"
34 #include "konqview.h"
35 #include "konqrun.h"
36 #include "konqmisc.h"
37 #include "konqviewmanager.h"
38 #include "konqframestatusbar.h"
39 #include "konqtabs.h"
40 #include "konqactions.h"
41 #include "konqsettingsxt.h"
42 #include "konqextensionmanager.h"
43 #include "konqueror_interface.h"
44 #include "delayedinitializer.h"
45 #include "konqextendedbookmarkowner.h"
46 #include "konqframevisitor.h"
47 #include "konqbookmarkbar.h"
48 #include "konqundomanager.h"
49 #include <config-konqueror.h>
50 #include <kstringhandler.h>
52 #include <konq_events.h>
53 #include <konqpixmapprovider.h>
54 #include <konq_operations.h>
55 #include <kbookmarkmanager.h>
56 #include <kinputdialog.h>
57 #include <klineedit.h>
58 #include <kanimatedbutton.h>
59 #include <kzip.h>
60 #include <pwd.h>
61 // we define STRICT_ANSI to get rid of some warnings in glibc
62 #ifndef __STRICT_ANSI__
63 #define __STRICT_ANSI__
64 #define _WE_DEFINED_IT_
65 #endif
66 #include <netdb.h>
67 #ifdef _WE_DEFINED_IT_
68 #undef __STRICT_ANSI__
69 #undef _WE_DEFINED_IT_
70 #endif
71 #include <assert.h>
72 #include <stdlib.h>
73 #include <time.h>
74 #include <kde_file.h>
75 #include <sys/types.h>
76 #include <sys/stat.h>
77 #include <unistd.h>
79 #include <QtCore/QFile>
80 #include <QtGui/QClipboard>
81 #include <QtCore/QArgument>
82 #include <QtGui/QLayout>
83 #include <QStackedWidget>
84 #include <QtCore/QFileInfo>
85 #ifdef Q_WS_X11
86 #include <QX11Info>
87 #endif
88 #include <QtCore/QEvent>
89 #include <QtGui/QKeyEvent>
90 #include <QtCore/QByteRef>
91 #include <QtCore/QList>
92 #include <QtGui/QPixmap>
93 #include <QtGui/QLineEdit>
95 #include <kaboutdata.h>
96 #include <ktoolbar.h>
97 #include <konqbookmarkmenu.h>
98 #include <kcmultidialog.h>
99 #include <kdebug.h>
100 #include <kedittoolbar.h>
101 #include <klocalizedstring.h>
102 #include <kmenubar.h>
103 #include <kmessagebox.h>
104 #include <knewmenu.h>
105 #include <konq_popupmenu.h>
106 #include "konqsettings.h"
107 #include <kprotocolinfo.h>
108 #include <kprotocolmanager.h>
109 #include <kstandardshortcut.h>
110 #include <kstandardaction.h>
111 #include <kstandarddirs.h>
112 #include <ksycoca.h>
113 #include <ktemporaryfile.h>
114 #include <ktogglefullscreenaction.h>
115 #include <ktoolbarpopupaction.h>
116 #include <kurlcompletion.h>
117 #include <kurlrequesterdialog.h>
118 #include <kurlrequester.h>
119 #include <kmimetypetrader.h>
120 #include <kwindowsystem.h>
121 #include <kfiledialog.h>
122 #include <klocale.h>
123 #include <kicon.h>
124 #include <kiconloader.h>
125 #include <kmenu.h>
126 #include <kprocess.h>
127 #include <kio/scheduler.h>
128 #include <kio/netaccess.h>
129 #include <kacceleratormanager.h>
130 #include <kuser.h>
131 #include <kxmlguifactory.h>
132 #include <netwm.h>
133 #include <sonnet/configdialog.h>
134 #ifdef KDE_MALLINFO_MALLOC
135 #include <malloc.h>
136 #endif
138 #include <sys/time.h>
139 #ifdef Q_WS_X11
140 #include <X11/Xlib.h>
141 #include <X11/Xatom.h>
142 #include <fixx11h.h>
143 #endif
144 #include <kauthorized.h>
145 #include <ktoolinvocation.h>
146 #include <QtDBus/QtDBus>
147 #include <kconfiggroup.h>
149 template class QList<QPixmap*>;
150 template class QList<KToggleAction*>;
152 KBookmarkManager* s_bookmarkManager = 0;
153 QList<KonqMainWindow*> *KonqMainWindow::s_lstViews = 0;
154 KConfig * KonqMainWindow::s_comboConfig = 0;
155 KCompletion * KonqMainWindow::s_pCompletion = 0;
156 QFile * KonqMainWindow::s_crashlog_file = 0;
158 bool KonqMainWindow::s_preloaded = false;
159 KonqMainWindow* KonqMainWindow::s_preloadedWindow = 0;
160 static int s_initialMemoryUsage = -1;
161 static time_t s_startupTime;
162 static int s_preloadUsageCount;
164 KonqOpenURLRequest KonqOpenURLRequest::null;
166 static int current_memory_usage( int* limit = NULL );
168 static unsigned short int s_closedItemsListLength = 10;
169 static unsigned long s_konqMainWindowInstancesCount = 0;
171 KonqExtendedBookmarkOwner::KonqExtendedBookmarkOwner(KonqMainWindow *w)
173 m_pKonqMainWindow = w;
176 KonqMainWindow::KonqMainWindow( const KUrl &initialURL, const QString& xmluiFile)
177 : KParts::MainWindow()
178 , m_paClosedItems(0)
179 , m_fullyConstructed(false)
181 incInstancesCount();
182 setPreloadedFlag( false );
184 if ( !s_lstViews )
185 s_lstViews = new QList<KonqMainWindow*>;
187 s_lstViews->append( this );
189 m_urlCompletionStarted = false;
191 m_currentView = 0;
192 m_pChildFrame = 0;
193 m_pActiveChild = 0;
194 m_pWorkingTab = 0;
195 m_pBookmarkMenu = 0;
196 (void) new KonqMainWindowAdaptor( this );
197 m_combo = 0;
198 m_bURLEnterLock = false;
199 m_bLocationBarConnected = false;
200 m_paBookmarkBar = 0;
201 m_pURLCompletion = 0;
202 m_goBuffer = 0;
203 m_configureDialog = 0;
205 m_viewModesGroup = new QActionGroup(this);
206 m_viewModesGroup->setExclusive(true);
207 connect(m_viewModesGroup, SIGNAL(triggered(QAction*)),
208 this, SLOT(slotViewModeTriggered(QAction*)),
209 Qt::QueuedConnection); // Queued so that we don't delete the action from the code that triggered it.
211 m_prevMenuBarVisible = true;
213 // This has to be called before any action is created for this mainwindow
214 setComponentData(KGlobal::mainComponent(), false /*don't load plugins yet*/);
216 m_pViewManager = new KonqViewManager( this );
218 m_viewModeMenu = 0;
219 m_openWithMenu = 0;
220 m_paCopyFiles = 0;
221 m_paMoveFiles = 0;
222 m_bookmarkBarInitialized = false;
224 m_toggleViewGUIClient = new ToggleViewGUIClient( this );
226 m_pBookmarksOwner = new KonqExtendedBookmarkOwner(this);
228 // init history-manager, load history, get completion object
229 if ( !s_pCompletion ) {
230 s_bookmarkManager = KBookmarkManager::userBookmarksManager();
232 // let the KBookmarkManager know that we are a browser, equals to "keditbookmarks --browser"
233 s_bookmarkManager->setEditorOptions("konqueror", true);
235 KonqHistoryManager* mgr = new KonqHistoryManager(s_bookmarkManager);
236 s_pCompletion = mgr->completionObject();
238 // setup the completion object before createGUI(), so that the combo
239 // picks up the correct mode from the HistoryManager (in slotComboPlugged)
240 int mode = KonqSettings::settingsCompletionMode();
241 s_pCompletion->setCompletionMode( (KGlobalSettings::Completion) mode );
243 connect(KParts::HistoryProvider::self(), SIGNAL(cleared()), SLOT(slotClearComboHistory()));
245 KonqPixmapProvider *prov = KonqPixmapProvider::self();
246 if ( !s_comboConfig ) {
247 s_comboConfig = new KConfig("konq_history", KConfig::NoGlobals);
248 KonqCombo::setConfig( s_comboConfig );
249 KConfigGroup locationBarGroup( s_comboConfig, "Location Bar" );
250 prov->load( locationBarGroup, "ComboIconCache" );
253 connect( prov, SIGNAL( changed() ), SLOT( slotIconsChanged() ) );
255 m_pUndoManager = new KonqUndoManager(this);
256 connect( m_pUndoManager, SIGNAL( undoAvailable( bool ) ),
257 this, SLOT( slotUndoAvailable( bool ) ) );
259 initCombo();
260 initActions();
262 connect( KSycoca::self(), SIGNAL( databaseChanged() ),
263 this, SLOT( slotDatabaseChanged() ) );
265 connect( KGlobalSettings::self(), SIGNAL( kdisplayFontChanged()), SLOT(slotReconfigure()));
267 //load the xmlui file specified in the profile or the default konqueror.rc
268 setXMLFile( KonqViewManager::normalizedXMLFileName(xmluiFile) );
270 setStandardToolBarMenuEnabled( true );
272 createGUI( 0 );
274 m_combo->setParent( toolBar("locationToolBar") );
275 m_combo->setFont( KGlobalSettings::generalFont() );
276 m_combo->show();
278 checkDisableClearButton();
280 connect(toolBarMenuAction(),SIGNAL(triggered()),this,SLOT(slotForceSaveMainWindowSettings()) );
282 if ( !m_toggleViewGUIClient->empty() )
283 plugActionList( QLatin1String( "toggleview" ), m_toggleViewGUIClient->actions() );
284 else
286 delete m_toggleViewGUIClient;
287 m_toggleViewGUIClient = 0;
290 m_bHTMLAllowed = KonqSettings::htmlAllowed();
292 m_ptaUseHTML->setChecked( m_bHTMLAllowed );
294 m_bNeedApplyKonqMainWindowSettings = true;
296 if ( !initialURL.isEmpty() ) {
297 openFilteredUrl( initialURL.url() );
298 } else {
299 // silent
300 m_bNeedApplyKonqMainWindowSettings = false;
303 if ( !initialGeometrySet() )
304 resize( 700, 480 );
306 //kDebug(1202) << this << "done";
308 if( s_initialMemoryUsage == -1 )
310 s_initialMemoryUsage = current_memory_usage();
311 s_startupTime = time( NULL );
312 s_preloadUsageCount = 0;
314 KonqSessionManager::self();
315 m_fullyConstructed = true;
318 KonqMainWindow::~KonqMainWindow()
320 //kDebug(1202) << this;
322 delete m_pViewManager;
323 m_pViewManager = 0;
325 if (s_lstViews) {
326 s_lstViews->removeAll(this);
327 if (s_lstViews->isEmpty()) {
328 delete s_lstViews;
329 s_lstViews = 0;
333 qDeleteAll(m_openWithActions);
334 m_openWithActions.clear();
336 delete m_pBookmarkMenu;
337 delete m_paBookmarkBar;
338 delete m_pBookmarksOwner;
339 delete m_pURLCompletion;
340 delete m_paClosedItems;
342 if ( s_lstViews == 0 ) {
343 delete s_comboConfig;
344 s_comboConfig = 0;
347 delete m_configureDialog;
348 m_configureDialog = 0;
349 delete m_combo;
350 m_combo = 0;
351 delete m_locationLabel;
352 m_locationLabel = 0;
353 m_pUndoManager->disconnect();
354 delete m_pUndoManager;
355 decInstancesCount();
357 //kDebug(1202) << this << "done";
360 void KonqMainWindow::incInstancesCount()
362 s_konqMainWindowInstancesCount++;
365 void KonqMainWindow::decInstancesCount()
367 s_konqMainWindowInstancesCount--;
370 QWidget * KonqMainWindow::createContainer( QWidget *parent, int index, const QDomElement &element, QAction* &containerAction )
372 QWidget *res = KParts::MainWindow::createContainer( parent, index, element, containerAction );
374 static QString nameBookmarkBar = QLatin1String( "bookmarkToolBar" );
375 static QString tagToolBar = QLatin1String( "ToolBar" );
376 if ( res && (element.tagName() == tagToolBar) && (element.attribute( "name" ) == nameBookmarkBar) )
378 assert( ::qobject_cast<KToolBar*>( res ) );
379 if (!KAuthorized::authorizeKAction("bookmarks")) {
380 delete res;
381 return 0;
384 if ( !m_bookmarkBarInitialized ) {
385 // The actual menu needs a different action collection, so that the bookmarks
386 // don't appear in kedittoolbar
387 m_bookmarkBarInitialized = true;
388 DelayedInitializer *initializer = new DelayedInitializer( QEvent::Show, res );
389 connect( initializer, SIGNAL( initialize() ), this, SLOT(initBookmarkBar()) );
393 if (res && element.tagName() == QLatin1String("Menu")) {
394 const QString& menuName = element.attribute("name");
395 if (menuName == "edit" || menuName == "tools") {
396 Q_ASSERT(qobject_cast<QMenu*>(res));
397 KAcceleratorManager::manage(static_cast<QMenu *>(res));
401 return res;
404 void KonqMainWindow::initBookmarkBar()
406 KToolBar * bar = qFindChild<KToolBar *>( this, "bookmarkToolBar" );
408 if (!bar) return;
410 delete m_paBookmarkBar;
411 m_paBookmarkBar = new KBookmarkBar( s_bookmarkManager, m_pBookmarksOwner, bar, this );
413 // hide if empty
414 if (bar->actions().count() == 0 )
415 bar->hide();
418 void KonqMainWindow::removeContainer( QWidget *container, QWidget *parent, QDomElement &element, QAction* containerAction )
420 static QString nameBookmarkBar = QLatin1String( "bookmarkToolBar" );
421 static QString tagToolBar = QLatin1String( "ToolBar" );
423 if ( element.tagName() == tagToolBar && element.attribute( "name" ) == nameBookmarkBar )
425 assert( ::qobject_cast<KToolBar*>( container ) );
426 if (m_paBookmarkBar)
427 m_paBookmarkBar->clear();
430 KParts::MainWindow::removeContainer( container, parent, element, containerAction );
433 // Detect a name filter (e.g. *.txt) in the url.
434 // Note that KShortURIFilter does the same, but we have no way of getting it from there
436 // Note: this removes the filter from the URL.
437 QString KonqMainWindow::detectNameFilter( KUrl & url )
439 if ( !KProtocolManager::supportsListing(url) )
440 return QString();
442 // Look for wildcard selection
443 QString nameFilter;
444 QString path = url.path();
445 int lastSlash = path.lastIndexOf( '/' );
446 if ( lastSlash > -1 )
448 if ( !url.query().isEmpty() && lastSlash == (int)path.length()-1 ) { // In /tmp/?foo, foo isn't a query
449 path += url.query(); // includes the '?'
450 url.setQuery( QString() );
452 QString fileName = path.mid( lastSlash + 1 );
453 QString testPath = path.left( lastSlash + 1 );
454 if ( fileName.indexOf( '*' ) != -1 || fileName.indexOf( '[' ) != -1 || fileName.indexOf( '?' ) != -1 )
456 // Check that a file or dir with all the special chars in the filename doesn't exist
457 if ( url.isLocalFile() ? !QFile::exists( path ) : !KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, this ) )
459 nameFilter = fileName;
460 url.setFileName( QString() );
461 kDebug(1202) << "Found wildcard. nameFilter=" << nameFilter << " New url=" << url;
466 return nameFilter;
469 void KonqMainWindow::openFilteredUrl(const QString & url, const KonqOpenURLRequest & req)
471 // Filter URL to build a correct one
472 if (m_currentDir.isEmpty() && m_currentView)
473 m_currentDir = m_currentView->url().path( KUrl::AddTrailingSlash );
475 KUrl filteredURL ( KonqMisc::konqFilteredURL( this, url, m_currentDir ) );
476 kDebug(1202) << "url" << url << "filtered into" << filteredURL;
478 if ( filteredURL.isEmpty() ) // initially empty, or error (e.g. ~unknown_user)
479 return;
481 m_currentDir.clear();
483 openUrl(0, filteredURL, QString(), req);
485 // #4070: Give focus to view after URL was entered manually
486 // Note: we do it here if the view mode (i.e. part) wasn't changed
487 // If it is changed, then it's done in KonqView::changePart
488 if ( m_currentView && m_currentView->part() )
489 m_currentView->part()->widget()->setFocus();
493 void KonqMainWindow::openFilteredUrl(const QString & _url, bool inNewTab, bool tempFile)
495 KonqOpenURLRequest req( _url );
496 req.browserArgs.setNewTab(inNewTab);
497 req.newTabInFront = true;
498 req.tempFile = tempFile;
500 openFilteredUrl( _url, req );
503 void KonqMainWindow::openUrl(KonqView *_view, const KUrl &_url,
504 const QString &_mimeType, const KonqOpenURLRequest& _req,
505 bool trustedSource)
507 #ifndef NDEBUG // needed for req.debug()
508 kDebug(1202) << "url=" << _url << "mimeType=" << _mimeType
509 << "_req=" << _req.debug() << "view=" << _view;
510 #endif
512 // We like modifying args in this method :)
513 KUrl url(_url);
514 QString mimeType(_mimeType);
515 KonqOpenURLRequest req(_req);
517 if ( url.url() == "about:blank" )
519 mimeType = "text/html";
521 else if ( !url.isValid() )
523 KMessageBox::error(0, i18n("Malformed URL\n%1", url.url()));
524 return;
526 else if ( !KProtocolInfo::isKnownProtocol( url ) && url.protocol() != "about" )
528 KMessageBox::error(0, i18n("Protocol not supported\n%1", url.protocol()));
529 return;
532 QString nameFilter = detectNameFilter( url );
533 if ( !nameFilter.isEmpty() )
535 req.nameFilter = nameFilter;
536 url.setFileName( QString() );
539 KonqView *view = _view;
541 // When clicking a 'follow active' view (e.g. view is the sidebar),
542 // open the URL in the active view
543 if (view && view->isFollowActive())
544 view = m_currentView;
546 if (!view && !req.browserArgs.newTab())
547 view = m_currentView; /* Note, this can be 0, e.g. on startup */
548 else if (!view && req.browserArgs.newTab()) {
549 // The URL should be opened in a new tab. Let's create the tab right away,
550 // it gives faster user feedback (#163628). For a short while (kde-4.1-beta1)
551 // I removed this entire block so that we wouldn't end up with a useless tab when
552 // launching an external application for this mimetype. But user feedback
553 // in all cases is more important than empty tabs in some cases.
554 view = m_pViewManager->addTab("text/html",
555 QString(),
556 false,
557 req.openAfterCurrentPage);
558 if (view) {
559 view->setCaption(i18nc("@title:tab", "Loading..."));
560 view->setLocationBarURL(_url);
561 if (!req.browserArgs.frameName.isEmpty())
562 view->setViewName(req.browserArgs.frameName); // #44961
564 if (req.newTabInFront)
565 m_pViewManager->showTab(view);
567 updateViewActions(); //A new tab created -- we may need to enable the "remove tab" button (#56318)
568 } else {
569 req.browserArgs.setNewTab(false);
573 const QString oldLocationBarURL = m_combo->currentText();
574 if ( view )
576 if ( view == m_currentView )
578 //will do all the stuff below plus GUI stuff
579 abortLoading();
581 else
583 view->stop();
584 // Don't change location bar if not current view
588 // Fast mode for local files: do the stat ourselves instead of letting KRun do it.
589 if ( mimeType.isEmpty() && url.isLocalFile() )
591 QByteArray _path( QFile::encodeName(url.path()));
592 KDE_struct_stat buff;
593 if ( KDE_stat( _path.data(), &buff ) != -1 )
594 mimeType = KMimeType::findByUrl( url, buff.st_mode )->name();
597 if (url.isLocalFile()) {
598 // Generic mechanism for redirecting to tar:/<path>/ when clicking on a tar file,
599 // zip:/<path>/ when clicking on a zip file, etc.
600 // The .protocol file specifies the mimetype that the kioslave handles.
601 // Note that we don't use mimetype inheritance since we don't want to
602 // open OpenDocument files as zip folders...
603 // Also note that we do this here and not in openView anymore,
604 // because in the case of foo.bz2 we don't know the final mimetype, we need a konqrun...
605 const QString protocol = KProtocolManager::protocolForArchiveMimetype(mimeType);
606 if (!protocol.isEmpty() && KonqFMSettings::settings()->shouldEmbed(mimeType)) {
607 url.setProtocol( protocol );
608 if (mimeType == "application/x-webarchive") {
609 url.addPath("index.html");
610 mimeType = "text/html";
611 } else {
612 if (KProtocolManager::outputType(url) == KProtocolInfo::T_FILESYSTEM) {
613 url.adjustPath(KUrl::AddTrailingSlash);
614 mimeType = "inode/directory";
615 } else
616 mimeType.clear();
622 //kDebug(1202) << "trying openView for" << url << "( mimeType" << mimeType << ")";
623 if ( ( !mimeType.isEmpty() && mimeType != "application/octet-stream") ||
624 url.url() == "about:" || url.url().startsWith("about:konqueror") || url.url() == "about:plugins" )
626 KService::Ptr offer = KMimeTypeTrader::self()->preferredService(mimeType, "Application");
627 const bool associatedAppIsKonqueror = isMimeTypeAssociatedWithSelf( mimeType, offer );
628 // If the associated app is konqueror itself, then make sure we try to embed before bailing out.
629 if ( associatedAppIsKonqueror )
630 req.forceAutoEmbed = true;
632 // Built-in view ?
633 if ( !openView( mimeType, url, view /* can be 0 */, req ) )
635 //kDebug(1202) << "openView returned false";
636 // Are we following another view ? Then forget about this URL. Otherwise fire app.
637 if ( !req.followMode )
639 //kDebug(1202) << "we were not following. Fire app.";
640 // The logic below is similar to BrowserRun::handleNonEmbeddable(),
641 // but we don't have a BrowserRun instance here, and since it uses
642 // some virtual methods [like save, for KHTMLRun], we can't just
643 // move all the logic to static methods... catch 22...
645 if ( !url.isLocalFile() && !trustedSource && KonqRun::isTextExecutable( mimeType ) )
646 mimeType = "text/plain"; // view, don't execute
647 // Remote URL: save or open ?
648 QString protClass = KProtocolInfo::protocolClass(url.protocol());
649 bool open = url.isLocalFile() || protClass==":local";
650 if ( !open ) {
651 // Use askSave from filetypesrc
652 KMessageBox::setDontShowAskAgainConfig(KonqFMSettings::settings()->fileTypesConfig().data());
653 KParts::BrowserRun::AskSaveResult res = KonqRun::askSave( url, offer, mimeType );
654 KMessageBox::setDontShowAskAgainConfig(0);
655 if ( res == KParts::BrowserRun::Save )
656 KParts::BrowserRun::simpleSave( url, QString(), this );
657 open = ( res == KParts::BrowserRun::Open );
659 if ( open )
661 if ( associatedAppIsKonqueror && refuseExecutingKonqueror(mimeType) )
662 return;
663 KUrl::List lst;
664 lst.append(url);
665 //kDebug(1202) << "Got offer" << (offer ? offer->name() : QString("0"));
666 const bool allowExecution = trustedSource || KParts::BrowserRun::allowExecution( mimeType, url );
667 if ( allowExecution &&
668 ( KonqRun::isExecutable( mimeType ) || !offer || !KRun::run( *offer, lst, this ) ) )
670 setLocationBarURL( oldLocationBarURL ); // Revert to previous locationbar URL
671 (void)new KRun( url, this );
677 else // no known mimeType, use KonqRun
679 bool earlySetLocationBarURL = false;
680 if (!view && !m_currentView) // no view yet, e.g. starting with url as argument
681 earlySetLocationBarURL = true;
682 else if (view == m_currentView && view->url().isEmpty()) // opening in current view
683 earlySetLocationBarURL = true;
684 if (req.browserArgs.newTab()) // it's going into a new tab anyway
685 earlySetLocationBarURL = false;
686 if (earlySetLocationBarURL) {
687 // Show it for now in the location bar, but we'll need to store it in the view
688 // later on (can't do it yet since either view == 0 or updateHistoryEntry will be called).
689 kDebug(1202) << "url=" << url;
690 setLocationBarURL( url );
693 kDebug(1202) << "Creating new konqrun for" << url << "req.typedUrl=" << req.typedUrl;
695 KonqRun * run = new KonqRun( this, view /* can be 0 */, url, req, trustedSource );
697 // Never start in external browser
698 run->setEnableExternalBrowser(false);
700 if ( view )
701 view->setRun( run );
703 if ( view == m_currentView )
704 startAnimation();
706 connect( run, SIGNAL( finished() ), this, SLOT( slotRunFinished() ) );
710 bool KonqMainWindow::openView( QString mimeType, const KUrl &_url, KonqView *childView, const KonqOpenURLRequest& req )
712 // Second argument is referring URL
713 if ( !KAuthorized::authorizeUrlAction("open", childView ? childView->url() : KUrl(), _url) )
715 QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, _url.prettyUrl());
716 KMessageBox::queuedMessageBox( this, KMessageBox::Error, msg );
717 return true; // Nothing else to do.
720 if ( KonqRun::isExecutable( mimeType ) )
721 return false; // execute, don't open
722 // Contract: the caller of this method should ensure the view is stopped first.
724 #ifndef NDEBUG
725 kDebug(1202) << mimeType << _url << "childView=" << childView << "req:" << req.debug();
726 #endif
727 bool bOthersFollowed = false;
729 if ( childView )
731 // If we're not already following another view (and if we are not reloading)
732 if ( !req.followMode && !req.args.reload() && !m_pViewManager->isLoadingProfile() )
734 // When clicking a 'follow active' view (e.g. childView is the sidebar),
735 // open the URL in the active view
736 // (it won't do anything itself, since it's locked to its location)
737 if ( childView->isFollowActive() && childView != m_currentView )
739 abortLoading();
740 setLocationBarURL( _url );
741 KonqOpenURLRequest newreq;
742 newreq.forceAutoEmbed = true;
743 newreq.followMode = true;
744 newreq.args = req.args;
745 newreq.browserArgs = req.browserArgs;
746 bOthersFollowed = openView( mimeType, _url, m_currentView, newreq );
748 // "link views" feature, and "sidebar follows active view" feature
749 bOthersFollowed = makeViewsFollow(_url, req.args, req.browserArgs, mimeType, childView) || bOthersFollowed;
751 if ( childView->isLockedLocation() && !req.args.reload() /* allow to reload a locked view*/ )
752 return bOthersFollowed;
755 KUrl url(_url);
757 // In case we open an index.html, we want the location bar
758 // to still display the original URL (so that 'up' uses that URL,
759 // and since that's what the user entered).
760 // changePart will take care of setting and storing that url.
761 QString originalURL = url.pathOrUrl();
762 if (!req.nameFilter.isEmpty()) { // keep filter in location bar
763 if (!originalURL.endsWith('/'))
764 originalURL += '/';
765 originalURL += req.nameFilter;
768 QString serviceName; // default: none provided
769 const QString urlStr = url.url();
770 if ( urlStr == "about:" || urlStr.startsWith("about:konqueror") || urlStr == "about:plugins" ) {
771 mimeType = "KonqAboutPage"; // not KParts/ReadOnlyPart, it fills the Location menu ! :)
772 serviceName = "konq_aboutpage";
773 originalURL = req.typedUrl.isEmpty() ? QString() : req.typedUrl;
775 else if ( urlStr == "about:blank" && req.typedUrl.isEmpty() ) {
776 originalURL.clear();
780 bool forceAutoEmbed = req.forceAutoEmbed || req.userRequestedReload;
781 if (!req.typedUrl.isEmpty()) // the user _typed_ the URL, he wants it in Konq.
782 forceAutoEmbed = true;
783 if (url.protocol() == "about" || url.protocol() == "error")
784 forceAutoEmbed = true;
785 // Related to KonqFactory::createView
786 if (!forceAutoEmbed && !KonqFMSettings::settings()->shouldEmbed(mimeType)) {
787 kDebug(1202) << "KonqFMSettings says: don't embed this servicetype";
788 return false;
790 // Do we even have a part to embed? Otherwise don't ask, since we'd ask twice.
791 if (!forceAutoEmbed) {
792 KService::List partServiceOffers;
793 KonqFactory::getOffers(mimeType, &partServiceOffers);
794 if (partServiceOffers.isEmpty()) {
795 kDebug(1202) << "No part available for" << mimeType;
796 return false;
800 // If the protocol doesn't support writing (e.g. HTTP) then we might want to save instead of just embedding.
801 // So (if embedding would succeed, hence the checks above) we ask the user
802 // Otherwise the user will get asked 'open or save' in openUrl anyway.
803 if (!forceAutoEmbed && !KProtocolManager::supportsWriting(url)) {
804 QString suggestedFilename;
805 KonqRun* run = childView ? childView->run() : 0;
806 int attachment = 0;
807 if (run) {
808 suggestedFilename = run->suggestedFileName();
809 attachment = (run->serverSuggestsSave()) ? KParts::BrowserRun::AttachmentDisposition : KParts::BrowserRun::InlineDisposition;
812 // Use askEmbedOrSave from filetypesrc
813 KMessageBox::setDontShowAskAgainConfig(KonqFMSettings::settings()->fileTypesConfig().data());
815 KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
816 url, mimeType, suggestedFilename, attachment);
817 KMessageBox::setDontShowAskAgainConfig(0);
818 if (res == KParts::BrowserRun::Open)
819 forceAutoEmbed = true;
820 else if (res == KParts::BrowserRun::Cancel)
821 return true; // handled, don't do anything else
822 else { // Save
823 KParts::BrowserRun::simpleSave(url, suggestedFilename, this);
824 return true; // handled
829 // Look for which view mode to use, if a directory - not if view locked
830 if ( ( !childView || (!childView->isLockedViewMode()) )
831 && mimeType == "inode/directory" ) {
833 if ( url.isLocalFile() ) { // local, check .directory file
834 // Read HTMLAllowed in the .directory file, default to m_bHTMLAllowed
835 KUrl urlDotDir( url );
836 urlDotDir.addPath(".directory");
837 bool HTMLAllowed = m_bHTMLAllowed;
838 QFile f( urlDotDir.path() );
839 if ( f.open(QIODevice::ReadOnly) ) {
840 f.close();
841 KConfig config(urlDotDir.path(), KConfig::SimpleConfig);
842 KConfigGroup urlProperties( &config, "URL properties" );
843 HTMLAllowed = urlProperties.readEntry( "HTMLAllowed", m_bHTMLAllowed);
844 //serviceName = urlProperties.readEntry( "ViewMode", serviceName );
845 //kDebug(1202) << "serviceName=" << serviceName;
847 QString indexFile;
848 if ( HTMLAllowed &&
849 ( !( indexFile = findIndexFile( url.path() ) ).isEmpty() ) ) {
850 mimeType = "text/html";
851 url = KUrl(indexFile);
852 //serviceName.clear(); // cancel what we just set, this is not a dir finally
855 // Reflect this setting in the menu
856 m_ptaUseHTML->setChecked( HTMLAllowed );
860 bool ok = true;
861 if ( !childView )
863 if (req.browserArgs.newTab())
865 KonqFrameTabs* tabContainer = m_pViewManager->tabContainer();
866 int index = tabContainer->currentIndex();
867 childView = m_pViewManager->addTab( mimeType, serviceName, false, req.openAfterCurrentPage );
869 if (req.newTabInFront && childView)
871 if ( req.openAfterCurrentPage )
872 tabContainer->setCurrentIndex( index + 1 );
873 else
874 tabContainer->setCurrentIndex( tabContainer->count()-1 );
878 else
880 // Create a new view
881 // createFirstView always uses force auto-embed even if user setting is "separate viewer",
882 // since this window has no view yet - we don't want to keep an empty mainwindow.
883 // This can happen with e.g. application/pdf from a target="_blank" link, or window.open.
884 childView = m_pViewManager->createFirstView( mimeType, serviceName );
886 if ( childView )
888 enableAllActions( true );
889 m_currentView = childView;
893 if ( !childView )
894 return false; // It didn't work out.
896 childView->setViewName( m_initialFrameName.isEmpty() ? req.browserArgs.frameName : m_initialFrameName );
897 m_initialFrameName.clear();
899 else // We know the child view
901 if ( !childView->isLockedViewMode() ) {
902 if ( ok ) {
904 // When typing a new URL, the current context doesn't matter anymore
905 // -> select the preferred part for a given mimetype (even if the current part can handle this mimetype).
906 // This fixes the "get katepart and then type a website URL -> loaded into katepart" problem
907 // (first fixed in r168902 from 2002!, see also unittest KonqHtmlTest::textThenHtml())
909 if (!req.typedUrl.isEmpty() || !serviceName.isEmpty()) {
910 ok = childView->changePart( mimeType, serviceName, forceAutoEmbed );
911 } else {
912 ok = childView->ensureViewSupports( mimeType, forceAutoEmbed );
918 if (ok)
920 //kDebug(1202) << "req.nameFilter= " << req.nameFilter;
921 //kDebug(1202) << "req.typedUrl= " << req.typedUrl;
922 //kDebug(1202) << "Browser extension? " << (childView->browserExtension() ? "YES" : "NO");
923 //kDebug(1202) << "Referrer: " << req.args.metaData()["referrer"];
924 childView->setTypedURL( req.typedUrl );
925 if ( childView->part() )
926 childView->part()->setArguments( req.args );
927 if ( childView->browserExtension() )
928 childView->browserExtension()->setBrowserArguments( req.browserArgs );
929 #if 0
930 KonqDirPart* dirPart = ::qobject_cast<KonqDirPart*>( childView->part() );
931 if ( dirPart )
932 dirPart->setFilesToSelect( req.filesToSelect );
933 #endif
934 if ( !url.isEmpty() )
935 childView->openUrl( url, originalURL, req.nameFilter, req.tempFile );
937 //kDebug(1202) << "ok=" << ok << "bOthersFollowed=" << bOthersFollowed
938 // << "returning" << (ok || bOthersFollowed);
939 return ok || bOthersFollowed;
942 static KonqView * findChildView( KParts::ReadOnlyPart *callingPart, const QString &name, KonqMainWindow *&mainWindow, KParts::BrowserHostExtension *&hostExtension, KParts::ReadOnlyPart **part )
944 if ( !KonqMainWindow::mainWindowList() )
945 return 0;
947 foreach ( KonqMainWindow* window, *KonqMainWindow::mainWindowList() ) {
948 KonqView *res = window->childView( callingPart, name, hostExtension, part );
949 if ( res ) {
950 mainWindow = window;
951 return res;
955 return 0;
958 void KonqMainWindow::slotOpenURLRequest( const KUrl &url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments &browserArgs )
960 //kDebug(1202) << "frameName=" << browserArgs.frameName;
962 KParts::ReadOnlyPart *callingPart = static_cast<KParts::ReadOnlyPart *>( sender()->parent() );
963 QString frameName = browserArgs.frameName;
965 if ( !frameName.isEmpty() )
967 static QString _top = QLatin1String( "_top" );
968 static QString _self = QLatin1String( "_self" );
969 static QString _parent = QLatin1String( "_parent" );
970 static QString _blank = QLatin1String( "_blank" );
972 if ( frameName.toLower() == _blank )
974 slotCreateNewWindow( url, args, browserArgs );
975 return;
978 if ( frameName.toLower() != _top &&
979 frameName.toLower() != _self &&
980 frameName.toLower() != _parent )
982 KParts::BrowserHostExtension *hostExtension = 0;
983 KonqView *view = childView( callingPart, frameName, hostExtension, 0 );
984 if ( !view )
986 KonqMainWindow *mainWindow = 0;
987 view = findChildView( callingPart, frameName, mainWindow, hostExtension, 0 );
989 if ( !view || !mainWindow )
991 slotCreateNewWindow( url, args, browserArgs );
992 return;
995 if ( hostExtension )
996 hostExtension->openUrlInFrame( url, args, browserArgs );
997 else
998 mainWindow->openUrlRequestHelper( view, url, args, browserArgs );
999 return;
1002 if ( hostExtension )
1003 hostExtension->openUrlInFrame( url, args, browserArgs );
1004 else
1005 openUrlRequestHelper( view, url, args, browserArgs );
1006 return;
1010 KonqView *view = browserArgs.newTab() ? 0 : childView( callingPart );
1011 openUrlRequestHelper( view, url, args, browserArgs );
1014 //Called by slotOpenURLRequest
1015 void KonqMainWindow::openUrlRequestHelper( KonqView *childView, const KUrl &url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments &browserArgs )
1017 //kDebug(1202) << "url=" << url;
1018 KonqOpenURLRequest req;
1019 req.args = args;
1020 req.browserArgs = browserArgs;
1021 openUrl(childView, url, args.mimeType(), req, browserArgs.trustedSource);
1024 QObject *KonqMainWindow::lastFrame( KonqView *view )
1026 QObject *nextFrame, *viewFrame;
1027 nextFrame = view->frame();
1028 viewFrame = 0;
1029 while ( nextFrame != 0 && !::qobject_cast<QStackedWidget*>(nextFrame) ) {
1030 viewFrame = nextFrame;
1031 nextFrame = nextFrame->parent();
1033 return nextFrame ? viewFrame : 0;
1036 // Linked-views feature, plus "sidebar follows URL opened in the active view" feature
1037 bool KonqMainWindow::makeViewsFollow( const KUrl & url,
1038 const KParts::OpenUrlArguments& args,
1039 const KParts::BrowserArguments &browserArgs,
1040 const QString & serviceType, KonqView * senderView )
1042 if ( !senderView->isLinkedView() && senderView != m_currentView )
1043 return false; // none of those features apply -> return
1045 bool res = false;
1046 //kDebug(1202) << senderView->metaObject()->className() << "url=" << url << "serviceType=" << serviceType;
1047 KonqOpenURLRequest req;
1048 req.forceAutoEmbed = true;
1049 req.followMode = true;
1050 req.args = args;
1051 req.browserArgs = browserArgs;
1052 // We can't iterate over the map here, and openUrl for each, because the map can get modified
1053 // (e.g. by part changes). Better copy the views into a list.
1054 const QList<KonqView*> listViews = m_mapViews.values();
1056 QObject *senderFrame = lastFrame( senderView );
1058 foreach (KonqView * view, listViews)
1060 if (view == senderView)
1061 continue;
1062 bool followed = false;
1063 // Views that should follow this URL as both views are linked
1064 if (view->isLinkedView() && senderView->isLinkedView()) {
1065 QObject *viewFrame = lastFrame(view);
1067 // Only views in the same tab of the sender will follow
1068 if (senderFrame && viewFrame && viewFrame != senderFrame)
1069 continue;
1071 kDebug(1202) << "sending openUrl to view" << view->part()->metaObject()->className() << "url=" << url;
1073 // XXX duplicate code from ::openUrl
1074 if (view == m_currentView) {
1075 abortLoading();
1076 setLocationBarURL(url);
1077 } else {
1078 view->stop();
1081 followed = openView(serviceType, url, view, req);
1082 } else {
1083 // Make the sidebar follow the URLs opened in the active view
1084 if (view->isFollowActive() && senderView == m_currentView) {
1085 followed = openView(serviceType, url, view, req);
1089 // Ignore return value if the view followed but doesn't really
1090 // show the file contents. We still want to see that
1091 // file, e.g. in a separate viewer.
1092 // This happens in views locked to a directory mode,
1093 // like sidebar and konsolepart (#52161).
1094 const bool ignore = view->isLockedViewMode() && view->showsDirectory();
1095 //kDebug(1202) << "View " << view->service()->name()
1096 // << " supports dirs: " << view->showsDirectory()
1097 // << " is locked-view-mode:" << view->isLockedViewMode()
1098 // << " ignore=" << ignore;
1099 if ( !ignore )
1100 res = followed || res;
1103 return res;
1106 void KonqMainWindow::abortLoading()
1108 if ( m_currentView ) {
1109 m_currentView->stop(); // will take care of the statusbar
1110 stopAnimation();
1114 // Are there any indications that this window has a strong popup
1115 // nature and should therefore not be embedded into a tab?
1116 static bool isPopupWindow( const KParts::WindowArgs &windowArgs )
1118 // ### other settings to respect?
1119 return windowArgs.x() != -1 || windowArgs.y() != -1 ||
1120 windowArgs.width() != -1 || windowArgs.height() != -1 ||
1121 !windowArgs.isMenuBarVisible() ||
1122 !windowArgs.toolBarsVisible() ||
1123 !windowArgs.isStatusBarVisible();
1126 // This is called for the javascript window.open call.
1127 // Also called for MMB on link, target="_blank" link, MMB on folder, etc.
1128 void KonqMainWindow::slotCreateNewWindow( const KUrl &url,
1129 const KParts::OpenUrlArguments& args,
1130 const KParts::BrowserArguments &browserArgs,
1131 const KParts::WindowArgs &windowArgs, KParts::ReadOnlyPart **part )
1133 // NOTE: 'part' may be null
1135 kDebug(1202) << "url=" << url << "args.mimeType()=" << args.mimeType()
1136 << "browserArgs.frameName=" << browserArgs.frameName;
1138 if ( part )
1139 *part = 0; // Make sure to be initialized in case of failure...
1141 KonqMainWindow *mainWindow = 0;
1142 if ( !browserArgs.frameName.isEmpty() && browserArgs.frameName.toLower() != "_blank" ) {
1143 KParts::BrowserHostExtension *hostExtension = 0;
1144 KParts::ReadOnlyPart *ro_part = 0;
1145 KParts::BrowserExtension *be = ::qobject_cast<KParts::BrowserExtension *>(sender());
1146 if (be)
1147 ro_part = ::qobject_cast<KParts::ReadOnlyPart *>(be->parent());
1148 if ( findChildView( ro_part, browserArgs.frameName, mainWindow, hostExtension, part ) ) {
1149 // Found a view. If url isn't empty, we should open it - but this never happens currently
1150 // findChildView put the resulting part in 'part', so we can just return now
1151 //kDebug() << "frame=" << browserArgs.frameName << "-> found part=" << part << part->name();
1152 return;
1156 bool createTab = false;
1157 if (args.actionRequestedByUser()) { // MMB or some RMB popupmenu action
1158 createTab = KonqSettings::mmbOpensTab() &&
1159 !args.metaData().contains("forcenewwindow"); // RMB / Frame / Open in New Window
1160 } else {
1161 createTab = KonqSettings::popupsWithinTabs() &&
1162 !isPopupWindow( windowArgs );
1165 kDebug() << "createTab=" << createTab << "part=" << part;
1167 if ( createTab ) {
1169 bool newtabsinfront = KonqSettings::newTabsInFront();
1170 if ( windowArgs.lowerWindow() || (QApplication::keyboardModifiers() & Qt::ShiftModifier))
1171 newtabsinfront = !newtabsinfront;
1172 const bool aftercurrentpage = KonqSettings::openAfterCurrentPage();
1174 // Can we use the standard way (openUrl), or do we need the part pointer immediately?
1175 if (!part) {
1176 KonqOpenURLRequest req;
1177 req.browserArgs.setNewTab(true);
1178 req.newTabInFront = newtabsinfront;
1179 req.openAfterCurrentPage = aftercurrentpage;
1180 openUrl(0, url, args.mimeType(), req);
1181 } else {
1182 KonqView* newView = m_pViewManager->addTab("text/html", QString(), false, aftercurrentpage);
1183 if (newView == 0) return;
1185 if (newtabsinfront)
1186 m_pViewManager->showTab( newView );
1188 openUrl( newView, url.isEmpty() ? KUrl("about:blank") : url, QString() );
1189 newView->setViewName( browserArgs.frameName );
1191 *part = newView->part();
1193 return;
1196 // Pass the URL to createNewWindow so that it can select the right profile for it
1197 // Note that it's always empty in case of window.open, though.
1198 mainWindow = KonqMisc::createNewWindow(url, args, browserArgs, false, QStringList(), false, false /*do not open URL*/);
1199 mainWindow->resetAutoSaveSettings(); // Don't autosave
1201 KonqOpenURLRequest req;
1202 req.args = args;
1203 req.browserArgs = browserArgs;
1204 req.browserArgs.setNewTab(false); // we got a new window, no need for a new tab in that window
1205 req.forceAutoEmbed = true;
1207 // Do we know the mimetype? If not, go to generic openUrl which will use a KonqRun.
1208 if ( args.mimeType().isEmpty() ) {
1209 mainWindow->openUrl( 0, url, QString(), req );
1210 } else if (!mainWindow->openView(args.mimeType(), url, m_currentView, req)) {
1211 // we have problems. abort.
1212 delete mainWindow;
1214 if ( part )
1215 *part = 0;
1216 return;
1219 KonqView * view = 0;
1220 // cannot use activePart/currentView, because the activation through the partmanager
1221 // is delayed by a singleshot timer (see KonqViewManager::setActivePart)
1222 // ### TODO: not true anymore
1223 if ( mainWindow->viewMap().count() )
1225 MapViews::ConstIterator it = mainWindow->viewMap().begin();
1226 view = it.value();
1228 if ( part )
1229 *part = it.key();
1232 // activate the view now in order to make the menuBar() hide call work
1233 if ( part && *part ) {
1234 mainWindow->viewManager()->setActivePart(*part);
1237 if ( windowArgs.x() != -1 )
1238 mainWindow->move( windowArgs.x(), mainWindow->y() );
1239 if ( windowArgs.y() != -1 )
1240 mainWindow->move( mainWindow->x(), windowArgs.y() );
1242 int width;
1243 if ( windowArgs.width() != -1 )
1244 width = windowArgs.width();
1245 else
1246 width = mainWindow->width();
1248 int height;
1249 if ( windowArgs.height() != -1 )
1250 height = windowArgs.height();
1251 else
1252 height = mainWindow->height();
1254 mainWindow->resize( width, height );
1256 // process the window args
1258 if ( !windowArgs.isMenuBarVisible() )
1260 mainWindow->menuBar()->hide();
1261 mainWindow->m_paShowMenuBar->setChecked( false );
1264 if ( !windowArgs.toolBarsVisible() )
1266 foreach (KToolBar* bar, mainWindow->findChildren<KToolBar*>())
1267 bar->hide();
1270 if ( view ) {
1271 if ( !windowArgs.scrollBarsVisible() )
1272 view->disableScrolling();
1273 if ( !windowArgs.isStatusBarVisible() )
1274 view->frame()->statusbar()->hide();
1277 if ( !windowArgs.isResizable() )
1278 // ### this doesn't seem to work :-(
1279 mainWindow->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
1281 // Trying to show the window initially behind the current window is a bit tricky,
1282 // as this involves the window manager, which may see things differently.
1283 // Many WMs raise and activate new windows, which means without WM support this won't work very
1284 // well. If the WM has support for _NET_WM_USER_TIME, it will be just set to 0 (=don't focus on show),
1285 // and the WM should take care of it itself.
1286 bool wm_usertime_support = false;
1288 #ifdef Q_WS_X11
1289 Time saved_last_input_time = QX11Info::appUserTime();
1290 if ( windowArgs.lowerWindow() )
1292 NETRootInfo wm_info( QX11Info::display(), NET::Supported );
1293 wm_usertime_support = wm_info.isSupported( NET::WM2UserTime );
1294 if( wm_usertime_support )
1296 // *sigh*, and I thought nobody would need QWidget::dontFocusOnShow().
1297 // Avoid Qt's support for user time by setting it to 0, and
1298 // set the property ourselves.
1299 QX11Info::setAppUserTime( 0 );
1300 KWindowSystem::setUserTime( mainWindow->winId(), 0 );
1302 // Put below the current window before showing, in case that actually works with the WM.
1303 // First do complete lower(), then stackUnder(), because the latter may not work with many WMs.
1304 mainWindow->lower();
1305 mainWindow->stackUnder( this );
1308 mainWindow->show();
1310 if ( windowArgs.lowerWindow() )
1312 QX11Info::setAppUserTime( saved_last_input_time );
1313 if( !wm_usertime_support )
1314 { // No WM support. Let's try ugly tricks.
1315 mainWindow->lower();
1316 mainWindow->stackUnder( this );
1317 if( this->isActiveWindow())
1318 this->activateWindow();
1321 #else // Q_WS_X11
1322 mainWindow->show();
1323 #endif
1325 if ( windowArgs.isFullScreen() )
1326 mainWindow->action( "fullscreen" )->trigger();
1329 void KonqMainWindow::slotNewWindow()
1331 // Use profile from current window, if set
1332 QString profile = m_pViewManager->currentProfile();
1333 if ( profile.isEmpty() )
1335 if ( m_currentView && m_currentView->url().protocol().startsWith( "http" ) )
1336 profile = QLatin1String("webbrowsing");
1337 else
1338 profile = QLatin1String("filemanagement");
1340 KonqMisc::createBrowserWindowFromProfile(
1341 KStandardDirs::locate( "data", QLatin1String("konqueror/profiles/")+profile ),
1342 profile );
1345 void KonqMainWindow::slotDuplicateWindow()
1347 m_pViewManager->duplicateWindow()->show();
1350 void KonqMainWindow::slotSendURL()
1352 const KUrl::List lst = currentURLs();
1353 QString body;
1354 QString fileNameList;
1355 for ( KUrl::List::ConstIterator it = lst.begin() ; it != lst.end() ; ++it )
1357 if ( !body.isEmpty() ) body += '\n';
1358 body += (*it).prettyUrl();
1359 if ( !fileNameList.isEmpty() ) fileNameList += ", ";
1360 fileNameList += (*it).fileName();
1362 QString subject;
1363 if (m_currentView && !m_currentView->showsDirectory())
1364 subject = m_currentView->caption();
1365 else // directory view
1366 subject = fileNameList;
1367 KToolInvocation::invokeMailer(QString(),QString(),QString(),
1368 subject, body);
1371 void KonqMainWindow::slotSendFile()
1373 const KUrl::List lst = currentURLs();
1374 QStringList urls;
1375 QString fileNameList;
1376 for ( KUrl::List::ConstIterator it = lst.begin() ; it != lst.end() ; ++it )
1378 if ( !fileNameList.isEmpty() ) fileNameList += ", ";
1379 if ( (*it).isLocalFile() && QFileInfo((*it).path()).isDir() )
1381 // Create a temp dir, so that we can put the ZIP file in it with a proper name
1382 QString zipFileName;
1384 //TODO This should use KTempDir
1385 KTemporaryFile zipFile;
1386 zipFile.open();
1387 zipFileName = zipFile.fileName();
1390 QDir().mkdir(zipFileName);
1391 zipFileName = zipFileName+'/'+(*it).fileName()+".zip";
1392 KZip zip( zipFileName );
1393 if ( !zip.open( QIODevice::WriteOnly ) )
1394 continue; // TODO error message
1395 zip.addLocalDirectory( (*it).path(), QString() );
1396 zip.close();
1397 fileNameList += (*it).fileName()+".zip";
1398 urls.append( zipFileName );
1400 else
1402 fileNameList += (*it).fileName();
1403 urls.append( (*it).url() );
1406 QString subject;
1407 if ( m_currentView && !m_currentView->showsDirectory())
1408 subject = m_currentView->caption();
1409 else
1410 subject = fileNameList;
1411 KToolInvocation::invokeMailer(QString(), QString(), QString(), subject,
1412 QString(), //body
1413 QString(),
1414 urls); // attachments
1417 void KonqMainWindow::slotOpenLocation()
1419 focusLocationBar();
1420 m_combo->lineEdit()->selectAll();
1423 void KonqMainWindow::slotOpenFile()
1425 KUrl currentUrl;
1426 if (m_currentView && m_currentView->url().isLocalFile())
1427 currentUrl = m_currentView->url();
1428 else
1429 currentUrl = KUrl::fromPath(QDir::homePath());
1431 KUrl url = KFileDialog::getOpenUrl(currentUrl, QString(), this);
1432 if (!url.isEmpty())
1433 openFilteredUrl( url.url().trimmed() );
1436 #if 0
1437 void KonqMainWindow::slotToolFind()
1439 if ( m_currentView && ::qobject_cast<KonqDirPart*>( m_currentView->part() ) )
1441 KonqDirPart* dirPart = static_cast<KonqDirPart *>(m_currentView->part());
1443 if (!m_paFindFiles->isChecked())
1445 dirPart->slotFindClosed();
1446 return;
1449 KonqFactory konqFactory;
1450 KonqViewFactory factory = konqFactory.createView( "Konqueror/FindPart" );
1451 if ( factory.isNull() )
1453 KMessageBox::error( this, i18n("Cannot create the find part, check your installation.") );
1454 m_paFindFiles->setChecked(false);
1455 return;
1458 KParts::ReadOnlyPart* findPart = factory.create( m_currentView->frame(), dirPart );
1459 dirPart->setFindPart( findPart );
1461 m_currentView->frame()->insertTopWidget( findPart->widget() );
1462 findPart->widget()->show();
1463 findPart->widget()->setFocus();
1465 connect( dirPart, SIGNAL( findClosed(KonqDirPart *) ),
1466 this, SLOT( slotFindClosed(KonqDirPart *) ) );
1468 else if ( ::qobject_cast<KAction*>(sender()) ) // don't go there if called by the singleShot below
1470 KUrl url;
1471 if ( m_currentView && m_currentView->url().isLocalFile() )
1472 url = m_currentView->locationBarURL();
1473 else
1474 url.setPath( QDir::homePath() );
1475 KonqMainWindow * mw = KonqMisc::createBrowserWindowFromProfile(
1476 KStandardDirs::locate( "data", QLatin1String("konqueror/profiles/filemanagement") ),
1477 "filemanagement", url, KParts::URLArgs(), true /* forbid "use html"*/ );
1478 mw->m_paFindFiles->setChecked(true);
1479 // Delay it after the openUrl call (hacky!)
1480 QTimer::singleShot( 1, mw, SLOT(slotToolFind()));
1481 m_paFindFiles->setChecked(false);
1484 #endif
1486 #if 0
1487 void KonqMainWindow::slotFindOpen( KonqDirPart * dirPart )
1489 Q_ASSERT( m_currentView );
1490 Q_ASSERT( m_currentView->part() == dirPart );
1491 slotToolFind(); // lazy me
1494 void KonqMainWindow::slotFindClosed( KonqDirPart * dirPart )
1496 KonqView * dirView = m_mapViews.value( dirPart );
1497 Q_ASSERT(dirView);
1498 if ( dirView && dirView == m_currentView )
1499 m_paFindFiles->setEnabled( true );
1500 m_paFindFiles->setChecked(false);
1502 #endif
1504 void KonqMainWindow::slotIconsChanged()
1506 kDebug(1202);
1507 m_combo->updatePixmaps();
1508 m_pViewManager->updatePixmaps();
1509 updateWindowIcon();
1512 void KonqMainWindow::slotOpenWith()
1514 KUrl::List lst;
1515 lst.append(m_currentView->url());
1517 const QString serviceName = sender()->objectName();
1519 const KService::List offers = m_currentView->appServiceOffers();
1520 KService::List::ConstIterator it = offers.begin();
1521 const KService::List::ConstIterator end = offers.end();
1522 for (; it != end; ++it ) {
1523 if ((*it)->desktopEntryName() == serviceName) {
1524 KRun::run(**it, lst, this);
1525 return;
1530 void KonqMainWindow::slotViewModeTriggered(QAction* action)
1532 // Gather data from the action, since the action will be deleted by changePart
1533 const QString modeName = action->objectName();
1534 const QString internalViewMode = action->data().toString();
1536 if ( m_currentView->service()->desktopEntryName() != modeName ) {
1537 m_currentView->stop();
1538 m_currentView->lockHistory();
1540 // Save those, because changePart will lose them
1541 KUrl url = m_currentView->url();
1542 QString locationBarURL = m_currentView->locationBarURL();
1543 #if 0
1544 QStringList filesToSelect;
1545 KonqDirPart* dirPart = ::qobject_cast<KonqDirPart *>(m_currentView->part());
1546 if( dirPart ) {
1547 const KFileItemList fileItemsToSelect = dirPart->selectedFileItems();
1548 KFileItemList::const_iterator it = fileItemsToSelect.begin();
1549 const KFileItemList::const_iterator end = fileItemsToSelect.end();
1550 for ( ; it != end; ++it ) {
1551 filesToSelect += (*it)->name();
1554 #endif
1556 m_currentView->changePart( m_currentView->serviceType(), modeName );
1557 KUrl locURL( locationBarURL );
1558 QString nameFilter = detectNameFilter( locURL );
1559 #if 0
1560 KonqDirPart* dirPart = ::qobject_cast<KonqDirPart *>(m_currentView->part());
1561 if( dirPart )
1562 dirPart->setFilesToSelect( filesToSelect );
1563 #endif
1564 m_currentView->openUrl( locURL, locationBarURL, nameFilter );
1567 if (!internalViewMode.isEmpty() && internalViewMode != m_currentView->internalViewMode()) {
1568 m_currentView->setInternalViewMode(internalViewMode);
1572 void KonqMainWindow::showHTML( KonqView * _view, bool b, bool _activateView )
1574 // Save this setting
1575 // This has to be done before calling openView since it relies on it
1576 KonqSettings::setHtmlAllowed( b );
1577 KonqSettings::self()->writeConfig();
1578 if ( _activateView )
1579 m_bHTMLAllowed = b;
1581 if ( b && _view->showsDirectory()) {
1582 _view->lockHistory();
1583 openView( "inode/directory", _view->url(), _view );
1585 else if ( !b && _view->supportsMimeType( "text/html" ) )
1587 KUrl u( _view->url() );
1588 QString fileName = u.fileName().toLower();
1589 if ( KProtocolManager::supportsListing( u ) && fileName.startsWith("index.htm") ) {
1590 _view->lockHistory();
1591 u.setPath( u.directory() );
1592 openView( "inode/directory", u, _view );
1597 void KonqMainWindow::slotShowHTML()
1599 bool b = !m_currentView->allowHTML();
1601 m_currentView->stop();
1602 m_currentView->setAllowHTML( b );
1603 showHTML( m_currentView, b, true ); //current view
1604 m_pViewManager->showHTML(b );
1608 void KonqMainWindow::setShowHTML( bool b )
1610 m_bHTMLAllowed = b;
1611 if ( m_currentView )
1612 m_currentView->setAllowHTML( b );
1613 m_ptaUseHTML->setChecked( b );
1616 void KonqMainWindow::slotLockView()
1618 m_currentView->setLockedLocation( m_paLockView->isChecked() );
1621 void KonqMainWindow::slotStop()
1623 abortLoading();
1624 if ( m_currentView )
1626 m_currentView->frame()->statusbar()->message( i18n("Canceled.") );
1630 void KonqMainWindow::slotLinkView()
1632 // Can't access this action in passive mode anyway
1633 assert(!m_currentView->isPassiveMode());
1634 bool mode = !m_currentView->isLinkedView();
1636 if (linkableViewsCount() == 2)
1638 // Exactly two linkable views : link both
1639 KonqMainWindow::MapViews::ConstIterator it = viewMap().begin();
1640 if( (*it)->isFollowActive() ) // skip sidebar
1641 ++it;
1642 (*it)->setLinkedView( mode );
1643 ++it;
1644 if( (*it)->isFollowActive() ) // skip sidebar
1645 ++it;
1646 (*it)->setLinkedView( mode );
1648 else // Normal case : just this view
1649 m_currentView->setLinkedView( mode );
1652 void KonqMainWindow::slotReload( KonqView* reloadView, bool softReload )
1654 if ( !reloadView )
1655 reloadView = m_currentView;
1657 if ( !reloadView || reloadView->url().isEmpty() )
1658 return;
1660 if ( reloadView->part() && (reloadView->part()->metaObject()->indexOfProperty("modified") != -1) ) {
1661 QVariant prop = reloadView->part()->property("modified");
1662 if (prop.isValid() && prop.toBool())
1663 if ( KMessageBox::warningContinueCancel( this,
1664 i18n("This page contains changes that have not been submitted.\nReloading the page will discard these changes."),
1665 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"view-refresh"), KStandardGuiItem::cancel(), "discardchangesreload") != KMessageBox::Continue )
1666 return;
1669 KonqOpenURLRequest req( reloadView->typedUrl() );
1670 req.userRequestedReload = true;
1671 if ( reloadView->prepareReload( req.args, req.browserArgs, softReload ) )
1673 reloadView->lockHistory();
1674 // Reuse current servicetype for local files, but not for remote files (it could have changed, e.g. over HTTP)
1675 QString serviceType = reloadView->url().isLocalFile() ? reloadView->serviceType() : QString();
1676 // By using locationBarURL instead of url, we preserve name filters (#54687)
1677 openUrl( reloadView, reloadView->locationBarURL(), serviceType, req );
1681 void KonqMainWindow::slotForceReload()
1683 // A forced reload is simply a "hard" (i.e. - not soft!) reload.
1684 slotReload(0L /* Current view */, false /* Not softReload*/);
1687 void KonqMainWindow::slotReloadPopup()
1689 if (m_pWorkingTab)
1690 slotReload( m_pWorkingTab->activeChildView() );
1693 void KonqMainWindow::slotHome(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
1695 const QString homeURL = m_currentView && m_currentView->showsDirectory() ? QDir::homePath()
1696 : KonqSettings::homeURL();
1698 KonqOpenURLRequest req;
1699 req.browserArgs.setNewTab(true);
1700 req.newTabInFront = KonqSettings::newTabsInFront();
1702 if (modifiers & Qt::ShiftModifier)
1703 req.newTabInFront = !req.newTabInFront;
1705 if( modifiers & Qt::ControlModifier ) // Ctrl Left/MMB
1706 openFilteredUrl( homeURL, req);
1707 else if( buttons & Qt::MidButton )
1709 if(KonqSettings::mmbOpensTab())
1710 openFilteredUrl( homeURL, req);
1711 else
1713 KUrl finalURL = KonqMisc::konqFilteredURL( this, homeURL );
1714 KonqMisc::createNewWindow( finalURL.url() );
1717 else
1718 openFilteredUrl( homeURL, false );
1721 void KonqMainWindow::slotHome()
1723 slotHome(Qt::LeftButton, Qt::NoModifier);
1726 void KonqMainWindow::slotGoHistory()
1728 QAction *a = m_toggleViewGUIClient->action("konq_sidebartng");
1729 if (!a) {
1730 KMessageBox::sorry(0, i18n("Your sidebar is not functional or unavailable."), i18n("Show History Sidebar"));
1731 return;
1734 // Show the sidebar
1735 if (!static_cast<KToggleAction*>(a)->isChecked()) {
1736 a->trigger();
1737 QTimer::singleShot( 0, this, SLOT(slotGoHistory()));
1738 return;
1741 // Tell it to show the history plugin
1742 MapViews::ConstIterator it;
1743 for (it = viewMap().begin(); it != viewMap().end(); ++it) {
1744 KonqView *view = it.value();
1745 if (view) {
1746 KService::Ptr svc = view->service();
1747 if (svc->desktopEntryName() == "konq_sidebartng") {
1748 if (!view->part()->openUrl( KUrl( "sidebar:history.desktop" ) ) )
1749 KMessageBox::sorry(0, i18n("Cannot find running history plugin in your sidebar."), i18n("Show History Sidebar"));
1750 break;
1756 void KonqMainWindow::slotConfigureExtensions()
1758 KonqExtensionManager extensionManager(this, this, m_currentView ? m_currentView->part() : 0);
1759 extensionManager.exec();
1762 void KonqMainWindow::slotConfigure()
1764 if( !m_configureDialog )
1766 m_configureDialog = new KCMultiDialog( this );
1767 m_configureDialog->setObjectName( "configureDialog" );
1768 connect(m_configureDialog, SIGNAL(finished()), this, SLOT(slotConfigureDone()));
1769 connect(m_configureDialog, SIGNAL(hidden()), this, SLOT(slotConfigureDone()));
1771 //BEGIN SYNC with initActions()
1772 const char* toplevelModules[]={
1773 "khtml_general",
1774 #ifndef Q_WS_WIN
1775 "kcmkonqyperformance",
1776 #endif
1777 "bookmarks"};
1778 for (uint i=0;i<sizeof(toplevelModules)/sizeof(char*);++i)
1779 if (KAuthorized::authorizeControlModule(toplevelModules[i]))
1780 m_configureDialog->addModule(KCModuleInfo(toplevelModules[i]));
1783 if (KAuthorized::authorizeControlModule("filebehavior") )
1785 KPageWidgetItem * fileManagementGroup = m_configureDialog->addModule("filebehavior");
1786 fileManagementGroup->setName(i18n("File Management"));
1787 const char* fmModules[]={
1788 "kcmdolphinviewmodes",
1789 "filetypes",
1790 "kcmtrash"};
1791 for (uint i=0;i<sizeof(fmModules)/sizeof(char*);++i)
1792 if (KAuthorized::authorizeControlModule(fmModules[i]))
1793 m_configureDialog->addModule(KCModuleInfo(fmModules[i]),fileManagementGroup);
1796 if (KAuthorized::authorizeControlModule("khtml_behavior"))
1798 KPageWidgetItem * webGroup = m_configureDialog->addModule("khtml_behavior");
1799 webGroup->setName(i18n("Web Browsing"));
1801 const char* webModules[]={
1802 "khtml_appearance",
1803 "khtml_filter",
1804 "ebrowsing",
1805 "cache",
1806 "proxy",
1807 "kcmhistory",
1808 "cookies",
1809 "crypto",
1810 "useragent",
1811 "khtml_java_js",
1812 "khtml_plugins"};
1813 for (uint i=0;i<sizeof(webModules)/sizeof(char*);++i)
1814 if (KAuthorized::authorizeControlModule(webModules[i]))
1815 m_configureDialog->addModule(KCModuleInfo(webModules[i]),webGroup);
1818 //END SYNC with initActions()
1822 m_configureDialog->show();
1826 void KonqMainWindow::slotConfigureDone()
1828 // Cleanup the dialog so other instances can use it..
1829 if ( m_configureDialog )
1831 m_configureDialog->deleteLater();
1832 m_configureDialog = 0;
1836 void KonqMainWindow::slotConfigureSpellChecking()
1838 Sonnet::ConfigDialog dialog( KGlobal::config().data(), this);
1839 dialog.setWindowIcon( KIcon( "konqueror" ));
1840 dialog.exec();
1843 void KonqMainWindow::slotConfigureToolbars()
1845 slotForceSaveMainWindowSettings();
1846 KEditToolBar dlg(factory(), this);
1847 connect(&dlg,SIGNAL(newToolBarConfig()),this,SLOT(slotNewToolbarConfig()));
1848 connect(&dlg,SIGNAL(newToolBarConfig()),this,SLOT(initBookmarkBar()));
1849 dlg.exec();
1850 checkDisableClearButton();
1853 void KonqMainWindow::slotNewToolbarConfig() // This is called when OK or Apply is clicked
1855 if ( m_toggleViewGUIClient )
1856 plugActionList( QLatin1String( "toggleview" ), m_toggleViewGUIClient->actions() );
1857 if ( m_currentView && m_currentView->appServiceOffers().count() > 0 )
1858 plugActionList( "openwith", m_openWithActions );
1860 plugViewModeActions();
1862 KConfigGroup cg = KGlobal::config()->group( "KonqMainWindow" );
1863 applyMainWindowSettings( cg );
1866 void KonqMainWindow::slotUndoAvailable( bool avail )
1868 m_paUndo->setEnabled( avail );
1871 void KonqMainWindow::slotPartChanged( KonqView *childView, KParts::ReadOnlyPart *oldPart, KParts::ReadOnlyPart *newPart )
1873 m_mapViews.remove( oldPart );
1874 m_mapViews.insert( newPart, childView );
1876 // Remove the old part, and add the new part to the manager
1877 // Note: this makes the new part active... so it calls slotPartActivated
1879 m_pViewManager->replacePart( oldPart, newPart, false );
1880 // Set active immediately
1881 m_pViewManager->setActivePart(newPart);
1883 viewsChanged();
1887 void KonqMainWindow::slotRunFinished()
1889 const KonqRun *run = static_cast<const KonqRun *>( sender() );
1891 if ( !run->mailtoURL().isEmpty() )
1893 KToolInvocation::invokeMailer( run->mailtoURL() );
1896 if ( run->hasError() ) { // we had an error
1897 QDBusMessage message = QDBusMessage::createSignal( KONQ_MAIN_PATH, "org.kde.Konqueror.Main", "removeFromCombo" );
1898 message << run->url().prettyUrl();
1899 QDBusConnection::sessionBus().send( message );
1902 KonqView *childView = run->childView();
1904 // Check if we found a mimetype _and_ we got no error (example: cancel in openwith dialog)
1905 if ( run->wasMimeTypeFound() && !run->hasError() )
1908 // We do this here and not in the constructor, because
1909 // we are waiting for the first view to be set up before doing this...
1910 // Note: this is only used when konqueror is started from command line.....
1911 if ( m_bNeedApplyKonqMainWindowSettings )
1913 m_bNeedApplyKonqMainWindowSettings = false; // only once
1914 applyKonqMainWindowSettings();
1917 return;
1920 // An error happened in KonqRun - stop wheel etc.
1922 if (childView) {
1923 childView->setLoading(false);
1925 if (childView == m_currentView) {
1926 stopAnimation();
1928 // Revert to working URL - unless the URL was typed manually
1929 if (run->typedUrl().isEmpty() && childView->currentHistoryEntry()) // not typed
1930 childView->setLocationBarURL(childView->currentHistoryEntry()->locationBarURL);
1932 } else { // No view, e.g. empty webbrowsing profile
1933 stopAnimation();
1937 void KonqMainWindow::applyKonqMainWindowSettings()
1939 const QStringList toggableViewsShown = KonqSettings::toggableViewsShown();
1940 QStringList::ConstIterator togIt = toggableViewsShown.begin();
1941 QStringList::ConstIterator togEnd = toggableViewsShown.end();
1942 for ( ; togIt != togEnd ; ++togIt )
1944 // Find the action by name
1945 // KAction * act = m_toggleViewGUIClient->actionCollection()->action( (*togIt).toLatin1() );
1946 QAction *act = m_toggleViewGUIClient->action( *togIt );
1947 if ( act )
1948 act->trigger();
1949 else
1950 kWarning(1202) << "Unknown toggable view in ToggableViewsShown " << *togIt ;
1954 void KonqMainWindow::slotSetStatusBarText( const QString & )
1956 // Reimplemented to disable KParts::MainWindow default behaviour
1957 // Does nothing here, see KonqFrame
1960 void KonqMainWindow::slotViewCompleted( KonqView * view )
1962 assert( view );
1964 // Need to update the current working directory
1965 // of the completion object every time the user
1966 // changes the directory!! (DA)
1967 if( m_pURLCompletion )
1969 KUrl u( view->locationBarURL() );
1970 if( u.isLocalFile() )
1971 m_pURLCompletion->setDir( u.path() );
1972 else
1973 m_pURLCompletion->setDir( u.url() ); //needs work!! (DA)
1977 void KonqMainWindow::slotPartActivated(KParts::Part *part)
1979 //kDebug(1202) << part
1980 // << (part && part->componentData().isValid() && part->componentData().aboutData() ? part->componentData().aboutData()->appName() : "");
1982 KonqView *newView = 0;
1983 KonqView *oldView = m_currentView;
1985 if (part) {
1986 newView = m_mapViews.value( static_cast<KParts::ReadOnlyPart *>(part) );
1987 Q_ASSERT(newView);
1988 if (newView->isPassiveMode()) {
1989 // Passive view. Don't connect anything, don't change m_currentView
1990 // Another view will become the current view very soon
1991 //kDebug(1202) << "Passive mode - return";
1992 return;
1996 KParts::BrowserExtension *ext = 0;
1998 if (oldView) {
1999 ext = oldView->browserExtension();
2000 if (ext) {
2001 //kDebug(1202) << "Disconnecting extension for view" << oldView;
2002 disconnectExtension( ext );
2006 //kDebug(1202) << "New current view" << newView;
2007 m_currentView = newView;
2008 if (!part) {
2009 //kDebug(1202) << "No part activated - returning";
2010 unplugViewModeActions();
2011 createGUI(0);
2012 KParts::MainWindow::setCaption(QString());
2013 return;
2016 ext = m_currentView->browserExtension();
2018 if (ext) {
2019 connectExtension(ext);
2020 } else {
2021 kDebug(1202) << "No Browser Extension for the new part";
2022 // Disable all browser-extension actions
2024 KParts::BrowserExtension::ActionSlotMap * actionSlotMap = KParts::BrowserExtension::actionSlotMapPtr();
2025 KParts::BrowserExtension::ActionSlotMap::ConstIterator it = actionSlotMap->constBegin();
2026 const KParts::BrowserExtension::ActionSlotMap::ConstIterator itEnd = actionSlotMap->constEnd();
2027 for (; it != itEnd ; ++it) {
2028 QAction * act = actionCollection()->action(QString::fromLatin1(it.key()));
2029 Q_ASSERT(act);
2030 if (act)
2031 act->setEnabled( false );
2034 if (m_paCopyFiles)
2035 m_paCopyFiles->setEnabled(false);
2036 if (m_paMoveFiles)
2037 m_paMoveFiles->setEnabled(false);
2040 createGUI(part);
2042 // View-dependent GUI
2044 KParts::MainWindow::setCaption( m_currentView->caption() );
2045 // This line causes #170470 when removing the current tab, because QTabBar
2046 // emits currentChanged before calling tabRemoved, so KTabWidget gets confused.
2047 // I don't see a need for it anyway...
2048 //m_currentView->frame()->setTitle(m_currentView->caption(), 0);
2050 updateOpenWithActions();
2051 updateViewActions(); // undo, lock, link and other view-dependent actions
2052 updateViewModeActions();
2054 m_paHome->setIcon(KIcon(m_currentView->showsDirectory() ? "user-home" : "go-home"));
2055 m_paHome->setText( m_currentView->showsDirectory() ? i18n( "Home Folder") : i18n( "Home Page" ) );
2056 m_paHome->setToolTip( m_currentView->showsDirectory() ? i18n( "Navigate to your 'Home Folder'") : i18n( "Navigate to your 'Home Page'" ) );
2057 m_paHome->setWhatsThis(m_currentView->showsDirectory() ? i18n( "Navigate to your local 'Home Folder'" ) :
2058 i18n( "<html>Navigate to your 'Home Page'<br /><br />"
2059 "You can configure the location where this button takes you "
2060 "under <b>Settings -> Configure Konqueror -> General</b>.</html>" ) );
2062 m_currentView->frame()->statusbar()->updateActiveStatus();
2064 if ( oldView && oldView->frame() )
2065 oldView->frame()->statusbar()->updateActiveStatus();
2067 //kDebug(1202) << "setting location bar url to"
2068 // << m_currentView->locationBarURL() << "m_currentView=" << m_currentView;
2069 m_currentView->setLocationBarURL( m_currentView->locationBarURL() );
2071 updateToolBarActions();
2073 m_currentView->setActiveComponent();
2076 void KonqMainWindow::insertChildView( KonqView *childView )
2078 //kDebug(1202) << childView;
2079 m_mapViews.insert(childView->part(), childView);
2081 connect(childView, SIGNAL(viewCompleted(KonqView *)),
2082 this, SLOT(slotViewCompleted(KonqView *)));
2084 if (!m_pViewManager->isLoadingProfile()) // see KonqViewManager::loadViewProfile
2085 viewCountChanged();
2086 emit viewAdded(childView);
2089 // Called by KonqViewManager, internal
2090 void KonqMainWindow::removeChildView( KonqView *childView )
2092 //kDebug(1202) << childView;
2094 disconnect( childView, SIGNAL( viewCompleted( KonqView * ) ),
2095 this, SLOT( slotViewCompleted( KonqView * ) ) );
2097 #ifndef NDEBUG
2098 //dumpViewList();
2099 #endif
2101 MapViews::Iterator it = m_mapViews.begin();
2102 const MapViews::Iterator end = m_mapViews.end();
2104 // find it in the map - can't use the key since childView->part() might be 0
2106 //kDebug(1202) << "Searching map";
2108 while ( it != end && it.value() != childView )
2109 ++it;
2111 //kDebug(1202) << "Verifying search results";
2113 if ( it == m_mapViews.end() )
2115 kWarning(1202) << "KonqMainWindow::removeChildView childView " << childView << " not in map !" ;
2116 return;
2119 //kDebug(1202) << "Removing view" << childView;
2121 m_mapViews.erase( it );
2123 viewCountChanged();
2124 emit viewRemoved( childView );
2126 #ifndef NDEBUG
2127 //dumpViewList();
2128 #endif
2130 // KonqViewManager takes care of m_currentView
2133 void KonqMainWindow::viewCountChanged()
2135 // This is called when the number of views changes.
2137 int lvc = linkableViewsCount();
2138 m_paLinkView->setEnabled( lvc > 1 );
2140 // Only one view (or one view + sidebar) -> make it/them unlinked
2141 if ( lvc == 1 ) {
2142 MapViews::Iterator it = m_mapViews.begin();
2143 MapViews::Iterator end = m_mapViews.end();
2144 for (; it != end; ++it )
2145 it.value()->setLinkedView( false );
2148 viewsChanged();
2150 m_pViewManager->viewCountChanged();
2153 void KonqMainWindow::viewsChanged()
2155 // This is called when the number of views changes OR when
2156 // the type of some view changes.
2158 // Nothing here anymore, but don't cleanup, some might come back later.
2160 updateViewActions(); // undo, lock, link and other view-dependent actions
2163 KonqView * KonqMainWindow::childView( KParts::ReadOnlyPart *view )
2165 MapViews::ConstIterator it = m_mapViews.constFind( view );
2166 if ( it != m_mapViews.constEnd() )
2167 return it.value();
2168 else
2169 return 0;
2172 KonqView * KonqMainWindow::childView( KParts::ReadOnlyPart *callingPart, const QString &name, KParts::BrowserHostExtension *&hostExtension, KParts::ReadOnlyPart **part )
2174 //kDebug() << "this=" << this << "looking for" << name;
2176 MapViews::ConstIterator it = m_mapViews.constBegin();
2177 MapViews::ConstIterator end = m_mapViews.constEnd();
2178 for (; it != end; ++it )
2180 KonqView* view = it.value();
2181 QString viewName = view->viewName();
2182 //kDebug() << " - viewName=" << viewName
2183 // << "frame names:" << view->frameNames();
2185 // First look for a hostextension containing this frame name
2186 KParts::BrowserHostExtension *ext = KParts::BrowserHostExtension::childObject( view->part() );
2187 if ( ext )
2189 ext = ext->findFrameParent(callingPart, name);
2190 kDebug(1202) << "BrowserHostExtension found part" << ext;
2191 if (!ext)
2192 continue; // Don't use this window
2195 if ( !viewName.isEmpty() && viewName == name )
2197 kDebug(1202) << "found existing view by name:" << view;
2198 hostExtension = 0;
2199 if ( part )
2200 *part = view->part();
2201 return view;
2204 // KParts::BrowserHostExtension* ext = KonqView::hostExtension( view->part(), name );
2206 if ( ext )
2208 const QList<KParts::ReadOnlyPart*> frames = ext->frames();
2209 QListIterator<KParts::ReadOnlyPart *> frameIt(frames);
2210 while (frameIt.hasNext())
2212 KParts::ReadOnlyPart *item = frameIt.next();
2213 if ( item->objectName() == name )
2215 kDebug(1202) << "found a frame of name" << name << ":" << item;
2216 hostExtension = ext;
2217 if ( part )
2218 *part = item;
2219 return view;
2225 return 0;
2228 int KonqMainWindow::activeViewsCount() const
2230 int res = 0;
2231 MapViews::ConstIterator end = m_mapViews.constEnd();
2232 for (MapViews::ConstIterator it = m_mapViews.constBegin(); it != end; ++it )
2233 if ( !it.value()->isPassiveMode() )
2234 ++res;
2236 return res;
2239 int KonqMainWindow::activeViewsNotLockedCount() const
2241 int res = 0;
2242 MapViews::ConstIterator end = m_mapViews.constEnd();
2243 for (MapViews::ConstIterator it = m_mapViews.constBegin(); it != end; ++it ) {
2244 if ( !it.value()->isPassiveMode() && !it.value()->isLockedLocation() )
2245 ++res;
2248 return res;
2251 int KonqMainWindow::linkableViewsCount() const
2253 int res = 0;
2254 MapViews::ConstIterator it = m_mapViews.constBegin();
2255 MapViews::ConstIterator end = m_mapViews.constEnd();
2256 for (; it != end; ++it )
2257 if ( !it.value()->isFollowActive() )
2258 ++res;
2260 return res;
2263 int KonqMainWindow::mainViewsCount() const
2265 int res = 0;
2266 MapViews::ConstIterator it = m_mapViews.constBegin();
2267 const MapViews::ConstIterator end = m_mapViews.constEnd();
2268 for (; it != end; ++it ) {
2269 if ( !it.value()->isPassiveMode() && !it.value()->isToggleView() ) {
2270 //kDebug(1202) << res << it.value() << it.value()->part()->widget();
2271 ++res;
2275 return res;
2278 void KonqMainWindow::slotURLEntered(const QString &text, Qt::KeyboardModifiers modifiers)
2280 if (m_bURLEnterLock || text.isEmpty())
2281 return;
2283 m_bURLEnterLock = true;
2285 if ((modifiers & Qt::ControlModifier) || (modifiers & Qt::AltModifier)) {
2286 m_combo->setURL(m_currentView ? m_currentView->url().prettyUrl() : QString());
2287 openFilteredUrl(text.trimmed(), true /*inNewTab*/);
2288 } else {
2289 openFilteredUrl(text.trimmed());
2292 m_bURLEnterLock = false;
2295 void KonqMainWindow::slotSplitViewHorizontal()
2297 if ( !m_currentView )
2298 return;
2299 KonqView* oldView = m_currentView;
2300 KonqView* newView = m_pViewManager->splitView(m_currentView, Qt::Horizontal);
2301 if (newView == 0)
2302 return;
2303 KonqOpenURLRequest req;
2304 req.forceAutoEmbed = true;
2305 openView(oldView->serviceType(), oldView->url(), newView, req);
2308 void KonqMainWindow::slotSplitViewVertical()
2310 if ( !m_currentView )
2311 return;
2312 KonqView* oldView = m_currentView;
2313 KonqView* newView = m_pViewManager->splitView(m_currentView, Qt::Vertical);
2314 if (newView == 0)
2315 return;
2316 KonqOpenURLRequest req;
2317 req.forceAutoEmbed = true;
2318 openView(oldView->serviceType(), oldView->url(), newView, req);
2321 void KonqMainWindow::slotAddTab()
2323 // we can hardcode text/html because this is what about:blank will use anyway
2324 KonqView* newView = m_pViewManager->addTab("text/html",
2325 QString(),
2326 false,
2327 KonqSettings::openAfterCurrentPage());
2328 if (!newView)
2329 return;
2331 openUrl( newView, KUrl("about:blank"), QString() );
2333 //HACK!! QTabBar likes to steal focus when changing widgets. This can result
2334 //in a flicker since we don't want it to get focus we want the combo to get
2335 //or keep focus...
2336 QWidget *widget = newView->frame() && newView->frame()->part() ?
2337 newView->frame()->part()->widget() : 0;
2338 if (widget)
2339 widget->setFocusProxy(m_combo);
2341 m_pViewManager->showTab( newView );
2343 if (widget)
2344 widget->setFocusProxy(0);
2346 m_pWorkingTab = 0;
2349 void KonqMainWindow::slotDuplicateTab()
2351 if ( !m_currentView )
2352 return;
2353 // TODO does this work with splitted views? sounds like I'll get only the current view
2354 // in the new tab, not the whole contents of the current tab...
2355 m_pViewManager->duplicateTab( m_currentView->frame(), KonqSettings::openAfterCurrentPage() );
2358 void KonqMainWindow::slotDuplicateTabPopup()
2360 m_pViewManager->duplicateTab( m_pWorkingTab, KonqSettings::openAfterCurrentPage() );
2363 void KonqMainWindow::slotBreakOffTab()
2365 if ( !m_currentView )
2366 return;
2367 if (m_currentView->part() &&
2368 (m_currentView->part()->metaObject()->indexOfProperty("modified") != -1) ) {
2369 QVariant prop = m_currentView->part()->property("modified");
2370 if (prop.isValid() && prop.toBool())
2371 if ( KMessageBox::warningContinueCancel( this,
2372 i18n("This tab contains changes that have not been submitted.\nDetaching the tab will discard these changes."),
2373 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"tab-detach"), KStandardGuiItem::cancel(), "discardchangesdetach") != KMessageBox::Continue )
2374 return;
2377 m_pViewManager->breakOffTab( m_currentView->frame(), size() );
2378 updateViewActions();
2381 void KonqMainWindow::slotBreakOffTabPopup()
2383 KonqView* originalView = m_currentView;
2384 KonqView *view = m_pWorkingTab->activeChildView();
2385 if (view && view->part() && (view->part()->metaObject()->indexOfProperty("modified") != -1) ) {
2386 QVariant prop = view->part()->property("modified");
2387 if (prop.isValid() && prop.toBool()) {
2388 m_pViewManager->showTab( view );
2389 if ( KMessageBox::warningContinueCancel( this,
2390 i18n("This tab contains changes that have not been submitted.\nDetaching the tab will discard these changes."),
2391 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"tab-detach"), KStandardGuiItem::cancel(), "discardchangesdetach") != KMessageBox::Continue )
2393 m_pViewManager->showTab( originalView );
2394 return;
2398 m_pViewManager->showTab( originalView );
2400 //Can't do this safely here as the tabbar may disappear and we're
2401 //hanging off here.
2402 QTimer::singleShot(0, this, SLOT( slotBreakOffTabPopupDelayed() ) );
2405 void KonqMainWindow::slotBreakOffTabPopupDelayed()
2407 m_pViewManager->breakOffTab( m_pWorkingTab, size() );
2408 updateViewActions();
2411 void KonqMainWindow::slotPopupNewWindow()
2413 KFileItemList::const_iterator it = m_popupItems.constBegin();
2414 const KFileItemList::const_iterator end = m_popupItems.constEnd();
2415 for ( ; it != end; ++it ) {
2416 KonqMisc::createNewWindow((*it).targetUrl(), m_popupUrlArgs, m_popupUrlBrowserArgs);
2420 void KonqMainWindow::slotPopupThisWindow()
2422 openUrl(0, m_popupItems.first().url());
2425 void KonqMainWindow::slotPopupNewTab()
2427 bool openAfterCurrentPage = KonqSettings::openAfterCurrentPage();
2428 bool newTabsInFront = KonqSettings::newTabsInFront();
2430 if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
2431 newTabsInFront = !newTabsInFront;
2433 popupNewTab(newTabsInFront, openAfterCurrentPage);
2436 void KonqMainWindow::popupNewTab(bool infront, bool openAfterCurrentPage)
2438 KonqOpenURLRequest req;
2439 req.newTabInFront = false;
2440 req.forceAutoEmbed = true;
2441 req.openAfterCurrentPage = openAfterCurrentPage;
2442 req.args = m_popupUrlArgs;
2443 req.browserArgs = m_popupUrlBrowserArgs;
2444 req.browserArgs.setNewTab(true);
2446 for ( int i = 0; i < m_popupItems.count(); ++i )
2448 if ( infront && i == m_popupItems.count()-1 )
2450 req.newTabInFront = true;
2452 openUrl( 0, m_popupItems[i].targetUrl(), QString(), req );
2456 void KonqMainWindow::openMultiURL( const KUrl::List& url )
2458 KUrl::List::ConstIterator it = url.constBegin();
2459 const KUrl::List::ConstIterator end = url.constEnd();
2460 for (; it != end; ++it )
2462 KonqView* newView = m_pViewManager->addTab("text/html");
2463 Q_ASSERT( newView );
2464 if (newView == 0) continue;
2465 openUrl( newView, *it, QString() );
2466 m_pViewManager->showTab( newView );
2467 focusLocationBar();
2468 m_pWorkingTab = 0;
2472 void KonqMainWindow::slotRemoveView()
2474 if (m_currentView && m_currentView->part() &&
2475 (m_currentView->part()->metaObject()->indexOfProperty("modified") != -1) ) {
2476 QVariant prop = m_currentView->part()->property("modified");
2477 if (prop.isValid() && prop.toBool())
2478 if ( KMessageBox::warningContinueCancel( this,
2479 i18n("This view contains changes that have not been submitted.\nClosing the view will discard these changes."),
2480 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"view-close"), KStandardGuiItem::cancel(), "discardchangesclose") != KMessageBox::Continue )
2481 return;
2484 // takes care of choosing the new active view
2485 m_pViewManager->removeView( m_currentView );
2488 void KonqMainWindow::slotRemoveTab()
2490 if ( !m_currentView )
2491 return;
2492 if ( m_currentView->part() &&
2493 (m_currentView->part()->metaObject()->indexOfProperty("modified") != -1) ) {
2494 QVariant prop = m_currentView->part()->property("modified");
2495 if (prop.isValid() && prop.toBool())
2496 if ( KMessageBox::warningContinueCancel( this,
2497 i18n("This tab contains changes that have not been submitted.\nClosing the tab will discard these changes."),
2498 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"tab-close"), KStandardGuiItem::cancel(), "discardchangesclose") != KMessageBox::Continue )
2499 return;
2502 KonqFrameBase* frame = dynamic_cast<KonqFrameBase*>(m_pViewManager->tabContainer()->currentWidget());
2504 if(frame)
2505 m_pViewManager->removeTab( frame );
2508 void KonqMainWindow::slotRemoveTabPopup()
2510 KonqView *originalView = m_currentView;
2511 KonqView *view = m_pWorkingTab->activeChildView();
2512 if (view && view->part() && (view->part()->metaObject()->indexOfProperty("modified") != -1) ) {
2513 QVariant prop = view->part()->property("modified");
2514 if (prop.isValid() && prop.toBool()) {
2515 m_pViewManager->showTab( view );
2516 if ( KMessageBox::warningContinueCancel( this,
2517 i18n("This tab contains changes that have not been submitted.\nClosing the tab will discard these changes."),
2518 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"tab-close"), KStandardGuiItem::cancel(), "discardchangesclose") != KMessageBox::Continue )
2520 m_pViewManager->showTab( originalView );
2521 return;
2524 m_pViewManager->showTab( originalView );
2527 //Can't do immediately - may kill the tabbar, and we're in an event path down from it
2528 QTimer::singleShot( 0, this, SLOT( slotRemoveTabPopupDelayed() ) );
2531 void KonqMainWindow::slotRemoveTabPopupDelayed()
2533 m_pViewManager->removeTab( m_pWorkingTab );
2536 void KonqMainWindow::slotRemoveOtherTabs()
2538 // This action is triggered by the shortcut that removes other tabs, so
2539 // we need to set the working tab to the current tab
2540 m_pWorkingTab = m_pViewManager->tabContainer()->tabContaining(m_currentView->frame());
2541 slotRemoveOtherTabsPopup();
2544 void KonqMainWindow::slotRemoveOtherTabsPopup()
2546 if ( KMessageBox::warningContinueCancel( this,
2547 i18n("Do you really want to close all other tabs?"),
2548 i18n("Close Other Tabs Confirmation"), KGuiItem(i18n("Close &Other Tabs"),"tab-close-other"),
2549 KStandardGuiItem::cancel(), "CloseOtherTabConfirm") != KMessageBox::Continue )
2550 return;
2552 KonqView *originalView = m_currentView;
2553 MapViews::ConstIterator it = m_mapViews.constBegin();
2554 MapViews::ConstIterator end = m_mapViews.constEnd();
2555 for (; it != end; ++it ) {
2556 KonqView *view = it.value();
2557 // m_currentView might be a view contained inside a splitted view so what we'll
2558 // do here is just compare if the views are inside the same tab.
2559 if ( view != originalView && view && m_pViewManager->tabContainer()->tabContaining(view->frame()) != m_pWorkingTab &&
2560 view->part() && (view->part()->metaObject()->indexOfProperty("modified") != -1) ) {
2561 QVariant prop = view->part()->property("modified");
2562 if (prop.isValid() && prop.toBool()) {
2563 m_pViewManager->showTab( view );
2564 if ( KMessageBox::warningContinueCancel( this,
2565 i18n("This tab contains changes that have not been submitted.\nClosing other tabs will discard these changes."),
2566 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"tab-close"), KStandardGuiItem::cancel(), "discardchangescloseother") != KMessageBox::Continue )
2568 m_pViewManager->showTab( originalView );
2569 return;
2574 m_pViewManager->showTab( originalView );
2576 //Can't do immediately - kills the tabbar, and we're in an event path down from it
2577 QTimer::singleShot( 0, this, SLOT( slotRemoveOtherTabsPopupDelayed() ) );
2580 void KonqMainWindow::slotRemoveOtherTabsPopupDelayed()
2582 m_pViewManager->removeOtherTabs( m_pWorkingTab );
2583 updateViewActions();
2586 void KonqMainWindow::slotReloadAllTabs()
2588 KonqView *originalView = m_currentView;
2589 MapViews::ConstIterator it = m_mapViews.constBegin();
2590 MapViews::ConstIterator end = m_mapViews.constEnd();
2591 for (; it != end; ++it ) {
2592 KonqView *view = it.value();
2593 if (view && view->part() && (view->part()->metaObject()->indexOfProperty("modified") != -1) ) {
2594 QVariant prop = view->part()->property("modified");
2595 if (prop.isValid() && prop.toBool()) {
2596 m_pViewManager->showTab( view );
2597 if ( KMessageBox::warningContinueCancel( this,
2598 i18n("This tab contains changes that have not been submitted.\nReloading all tabs will discard these changes."),
2599 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"view-refresh"), KStandardGuiItem::cancel(), "discardchangesreload") != KMessageBox::Continue )
2601 m_pViewManager->showTab( originalView );
2602 return;
2607 m_pViewManager->showTab( originalView );
2609 m_pViewManager->reloadAllTabs();
2610 updateViewActions();
2614 void KonqMainWindow::slotActivateNextTab()
2616 m_pViewManager->activateNextTab();
2619 void KonqMainWindow::slotActivatePrevTab()
2621 m_pViewManager->activatePrevTab();
2624 void KonqMainWindow::slotActivateTab()
2626 m_pViewManager->activateTab( sender()->objectName().right( 2 ).toInt() -1 );
2629 void KonqMainWindow::slotDumpDebugInfo()
2631 #ifndef NDEBUG
2632 dumpViewList();
2633 m_pViewManager->printFullHierarchy();
2634 #endif
2637 bool KonqMainWindow::askForTarget(const KLocalizedString& text, KUrl& url)
2639 const KUrl initialUrl = (viewCount()==2) ? otherView(m_currentView)->url() : m_currentView->url();
2640 QString label = text.subs( m_currentView->url().pathOrUrl() ).toString();
2641 KUrlRequesterDialog dlg(initialUrl.pathOrUrl(), label, this);
2642 dlg.setCaption(i18n("Enter Target"));
2643 dlg.urlRequester()->setMode( KFile::File | KFile::ExistingOnly | KFile::Directory );
2644 if (dlg.exec())
2646 url = dlg.selectedUrl();
2647 if ( url.isValid() )
2648 return true;
2649 else
2651 KMessageBox::error( this, i18n("<qt><b>%1</b> is not valid</qt>", url.url()));
2652 return false;
2655 return false;
2658 void KonqMainWindow::slotRequesterClicked( KUrlRequester *req )
2660 req->fileDialog()->setMode(KFile::Directory|KFile::ExistingOnly);
2663 void KonqMainWindow::slotCopyFiles()
2665 KUrl dest;
2666 if (!askForTarget(ki18n("Copy selected files from %1 to:"), dest))
2667 return;
2669 KonqOperations::copy(this, KonqOperations::COPY, currentURLs(), dest);
2672 void KonqMainWindow::slotMoveFiles()
2674 KUrl dest;
2675 if (!askForTarget(ki18n("Move selected files from %1 to:"), dest))
2676 return;
2678 KonqOperations::copy(this, KonqOperations::MOVE, currentURLs(), dest);
2681 KUrl::List KonqMainWindow::currentURLs() const
2683 KUrl::List urls;
2684 if ( m_currentView ) {
2685 urls.append( m_currentView->url() );
2686 #if 0
2687 KonqDirPart* dirPart = ::qobject_cast<KonqDirPart *>(m_currentView->part());
2688 if ( dirPart ) {
2689 const KFileItemList itemList = dirPart->selectedFileItems();
2690 if (!itemList.isEmpty()) { // Return list of selected items only if we have a selection
2691 urls = itemList.urlList();
2694 #endif
2696 return urls;
2699 // Only valid if there are one or two views
2700 KonqView * KonqMainWindow::otherView( KonqView * view ) const
2702 assert( viewCount() <= 2 );
2703 MapViews::ConstIterator it = m_mapViews.constBegin();
2704 if ( (*it) == view )
2705 ++it;
2706 if ( it != m_mapViews.constEnd() )
2707 return (*it);
2708 return 0;
2711 void KonqMainWindow::slotSaveViewProfile()
2713 m_pViewManager->showProfileDlg( m_pViewManager->currentProfile() );
2716 void KonqMainWindow::slotUpAboutToShow()
2718 QMenu *popup = m_paUp->menu();
2719 popup->clear();
2721 int i = 0;
2723 // Use the location bar URL, because in case we display a index.html
2724 // we want to go up from the dir, not from the index.html
2725 KUrl u(m_currentView->locationBarURL());
2726 u = u.upUrl();
2727 while (u.hasPath()) {
2728 QAction* action = new QAction(KIcon(KonqPixmapProvider::self()->iconNameFor(u)),
2729 u.pathOrUrl(),
2730 popup);
2731 action->setData(u);
2732 popup->addAction(action);
2734 if (u.path() == "/" || ++i > 10)
2735 break;
2737 u = u.upUrl();
2741 void KonqMainWindow::slotUp(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
2743 m_goMouseState = buttons;
2744 m_goKeyboardState = modifiers;
2745 QTimer::singleShot( 0, this, SLOT( slotUpDelayed() ) );
2748 void KonqMainWindow::slotUp()
2750 m_goMouseState = Qt::LeftButton;
2751 m_goKeyboardState = Qt::NoModifier;
2752 QTimer::singleShot( 0, this, SLOT( slotUpDelayed() ) );
2755 void KonqMainWindow::slotUpDelayed()
2757 KonqOpenURLRequest req;
2758 req.browserArgs.setNewTab(true);
2759 req.forceAutoEmbed = true;
2761 req.openAfterCurrentPage = KonqSettings::openAfterCurrentPage();
2762 req.newTabInFront = KonqSettings::newTabsInFront();
2764 if (m_goKeyboardState & Qt::ShiftModifier)
2765 req.newTabInFront = !req.newTabInFront;
2767 const QString& url = m_currentView->upUrl().url();
2768 if(m_goKeyboardState & Qt::ControlModifier)
2769 openFilteredUrl(url, req );
2770 else if(m_goMouseState & Qt::MidButton)
2772 if(KonqSettings::mmbOpensTab())
2773 openFilteredUrl( url, req);
2774 else
2775 KonqMisc::createNewWindow( url );
2777 else
2778 openFilteredUrl( url, false );
2779 m_goMouseState = Qt::LeftButton;
2782 void KonqMainWindow::slotUpActivated(QAction* action)
2784 openUrl( 0, action->data().value<KUrl>() );
2787 void KonqMainWindow::slotGoHistoryActivated( int steps )
2789 slotGoHistoryActivated( steps, Qt::LeftButton, Qt::NoModifier );
2792 void KonqMainWindow::slotGoHistoryActivated( int steps, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers )
2794 if (!m_goBuffer)
2796 // Only start 1 timer.
2797 m_goBuffer = steps;
2798 m_goMouseState = buttons;
2799 m_goKeyboardState = modifiers;
2800 QTimer::singleShot( 0, this, SLOT(slotGoHistoryDelayed()));
2804 void KonqMainWindow::slotGoHistoryDelayed()
2806 if (!m_currentView) return;
2808 bool openAfterCurrentPage = KonqSettings::openAfterCurrentPage();
2809 bool mmbOpensTab = KonqSettings::mmbOpensTab();
2810 bool inFront = KonqSettings::newTabsInFront();
2811 if(m_goKeyboardState & Qt::ShiftModifier)
2812 inFront = !inFront;
2814 if(m_goKeyboardState & Qt::ControlModifier)
2816 KonqView * newView = m_pViewManager->addTabFromHistory( m_currentView, m_goBuffer, openAfterCurrentPage );
2817 if (newView && inFront)
2818 m_pViewManager->showTab( newView );
2820 else if(m_goMouseState & Qt::MidButton)
2822 if(mmbOpensTab)
2824 KonqView * newView = m_pViewManager->addTabFromHistory( m_currentView, m_goBuffer, openAfterCurrentPage );
2825 if (newView && inFront)
2826 m_pViewManager->showTab( newView );
2828 else
2829 KonqMisc::newWindowFromHistory(this->currentView(), m_goBuffer);
2831 else
2833 m_currentView->go( m_goBuffer );
2834 makeViewsFollow(m_currentView->url(),
2835 KParts::OpenUrlArguments(),
2836 KParts::BrowserArguments(),
2837 m_currentView->serviceType(),
2838 m_currentView);
2841 m_goBuffer = 0;
2842 m_goMouseState = Qt::LeftButton;
2843 m_goKeyboardState = Qt::NoModifier;
2847 void KonqMainWindow::slotBackAboutToShow()
2849 m_paBack->menu()->clear();
2850 if (m_currentView)
2851 KonqActions::fillHistoryPopup(m_currentView->history(), m_currentView->historyIndex(), m_paBack->menu(), true, false);
2856 * Fill the closed tabs action menu before it's shown
2858 void KonqMainWindow::slotClosedItemsListAboutToShow()
2860 QMenu* popup = m_paClosedItems->menu();
2861 // Clear the menu and fill it with a maximum of s_closedItemsListLength number of urls
2862 popup->clear();
2863 QAction* clearAction = popup->addAction( i18nc("This menu entry empties the closed items history", "Empty Closed Items History") );
2864 connect(clearAction, SIGNAL(triggered()), m_pUndoManager, SLOT(clearClosedItemsList()));
2865 popup->insertSeparator((QAction*)0);
2867 QList<KonqClosedItem *>::ConstIterator it =
2868 m_pUndoManager->closedItemsList().constBegin();
2869 const QList<KonqClosedItem *>::ConstIterator end =
2870 m_pUndoManager->closedItemsList().constEnd();
2871 for ( int i = 0; it != end && i < s_closedItemsListLength; ++it, ++i ) {
2872 const QString text = QString::number(i) + ' ' + (*it)->title();
2873 QAction* action = popup->addAction( (*it)->icon(), text );
2874 action->setActionGroup(m_closedItemsGroup);
2875 action->setData(i);
2877 KAcceleratorManager::manage(popup);
2881 * Fill the sessions list action menu before it's shown
2883 void KonqMainWindow::slotSessionsListAboutToShow()
2885 QMenu* popup = m_paSessions->menu();
2886 // Clear the menu and fill it with a maximum of s_closedItemsListLength number of urls
2887 popup->clear();
2888 QAction* saveSessionAction = popup->addAction( KIcon("document-save"), i18n("Save As...") );
2889 connect(saveSessionAction, SIGNAL(triggered()), this, SLOT(saveCurrentSession()));
2890 QAction* manageSessionsAction = popup->addAction( KIcon("view-choose"), i18n("Manage...") );
2891 connect(manageSessionsAction, SIGNAL(triggered()), this, SLOT(manageSessions()));
2892 popup->insertSeparator((QAction*)0);
2894 QString dir= KStandardDirs::locateLocal("appdata", "sessions/");
2895 QDirIterator it(dir, QDir::Readable|QDir::NoDotAndDotDot|QDir::Dirs);
2897 while (it.hasNext())
2899 QFileInfo fileInfo(it.next());
2901 QAction* action = popup->addAction( fileInfo.baseName() );
2902 action->setActionGroup(m_sessionsGroup);
2903 action->setData(fileInfo.filePath());
2905 KAcceleratorManager::manage(popup);
2908 void KonqMainWindow::saveCurrentSession()
2910 KonqNewSessionDlg dlg( this );
2911 dlg.exec();
2914 void KonqMainWindow::manageSessions()
2916 KonqSessionDlg dlg( m_pViewManager, this );
2917 dlg.exec();
2920 void KonqMainWindow::slotSessionActivated(QAction* action)
2922 QString dirpath = action->data().toString();
2923 KonqSessionManager::self()->restoreSessions(dirpath);
2926 void KonqMainWindow::updateClosedItemsAction()
2928 bool available = m_pUndoManager->undoAvailable();
2929 m_paClosedItems->setEnabled(available);
2930 if(available)
2931 m_paUndo->setText(m_pUndoManager->undoText());
2934 void KonqMainWindow::slotBack()
2936 slotGoHistoryActivated(-1);
2939 void KonqMainWindow::slotBack(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
2941 slotGoHistoryActivated( -1, buttons, modifiers );
2944 void KonqMainWindow::slotBackActivated(QAction* action)
2946 KMenu* backMenu = static_cast<KMenu *>( m_paBack->menu() );
2947 slotGoHistoryActivated( action->data().toInt(), backMenu->mouseButtons(), backMenu->keyboardModifiers());
2950 void KonqMainWindow::slotForwardAboutToShow()
2952 m_paForward->menu()->clear();
2953 if (m_currentView)
2954 KonqActions::fillHistoryPopup(m_currentView->history(), m_currentView->historyIndex(), m_paForward->menu(), false, true);
2957 void KonqMainWindow::slotForward()
2959 slotGoHistoryActivated( 1 );
2962 void KonqMainWindow::slotForward(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
2964 slotGoHistoryActivated( 1, buttons, modifiers );
2967 void KonqMainWindow::slotForwardActivated(QAction* action)
2969 KMenu* forwardMenu = static_cast<KMenu *>( m_paForward->menu() );
2970 slotGoHistoryActivated( action->data().toInt(), forwardMenu->mouseButtons(), forwardMenu->keyboardModifiers() );
2973 void KonqMainWindow::checkDisableClearButton()
2975 // if the location toolbar already has the clear_location action,
2976 // disable the combobox's embedded clear icon.
2977 KToolBar* ltb = toolBar("locationToolBar");
2978 QAction* clearAction = action("clear_location");
2979 bool enable = true;
2980 foreach(QToolButton* atb, qFindChildren<QToolButton *>(ltb))
2982 if (atb->defaultAction() == clearAction) {
2983 enable = false;
2984 break;
2987 if (KLineEdit* kle = qobject_cast<KLineEdit*>(m_combo->lineEdit()))
2988 kle->setClearButtonShown( enable );
2991 void KonqMainWindow::initCombo()
2993 m_combo = new KonqCombo(0);
2995 m_combo->init( s_pCompletion );
2997 connect( m_combo, SIGNAL(activated(const QString&,Qt::KeyboardModifiers)),
2998 this, SLOT(slotURLEntered(const QString&,Qt::KeyboardModifiers)) );
2999 connect( m_combo, SIGNAL(showPageSecurity()),
3000 this, SLOT(showPageSecurity()) );
3002 m_pURLCompletion = new KUrlCompletion();
3003 m_pURLCompletion->setCompletionMode( s_pCompletion->completionMode() );
3005 // This only turns completion off. ~ is still there in the result
3006 // We do want completion of user names, right?
3007 //m_pURLCompletion->setReplaceHome( false ); // Leave ~ alone! Will be taken care of by filters!!
3009 connect( m_combo, SIGNAL(completionModeChanged(KGlobalSettings::Completion)),
3010 SLOT( slotCompletionModeChanged( KGlobalSettings::Completion )));
3011 connect( m_combo, SIGNAL( completion( const QString& )),
3012 SLOT( slotMakeCompletion( const QString& )));
3013 connect( m_combo, SIGNAL( substringCompletion( const QString& )),
3014 SLOT( slotSubstringcompletion( const QString& )));
3015 connect( m_combo, SIGNAL( textRotation( KCompletionBase::KeyBindingType) ),
3016 SLOT( slotRotation( KCompletionBase::KeyBindingType )));
3017 connect( m_combo, SIGNAL( cleared() ),
3018 SLOT ( slotClearHistory() ) );
3019 connect( m_pURLCompletion, SIGNAL( match(const QString&) ),
3020 SLOT( slotMatch(const QString&) ));
3022 m_combo->installEventFilter(this);
3024 static bool bookmarkCompletionInitialized = false;
3025 if ( !bookmarkCompletionInitialized )
3027 bookmarkCompletionInitialized = true;
3028 DelayedInitializer *initializer = new DelayedInitializer( QEvent::KeyPress, m_combo->lineEdit() );
3029 connect( initializer, SIGNAL( initialize() ), this, SLOT( bookmarksIntoCompletion() ) );
3033 void KonqMainWindow::bookmarksIntoCompletion()
3035 // add all bookmarks to the completion list for easy access
3036 bookmarksIntoCompletion( s_bookmarkManager->root() );
3039 // the user changed the completion mode in the combo
3040 void KonqMainWindow::slotCompletionModeChanged( KGlobalSettings::Completion m )
3042 s_pCompletion->setCompletionMode( m );
3044 KonqSettings::setSettingsCompletionMode( (int)m_combo->completionMode() );
3045 KonqSettings::self()->writeConfig();
3047 // tell the other windows too (only this instance currently)
3048 foreach ( KonqMainWindow* window, *s_lstViews ) {
3049 if ( window && window->m_combo ) {
3050 window->m_combo->setCompletionMode( m );
3051 window->m_pURLCompletion->setCompletionMode( m );
3056 // at first, try to find a completion in the current view, then use the global
3057 // completion (history)
3058 void KonqMainWindow::slotMakeCompletion( const QString& text )
3060 if( m_pURLCompletion )
3062 m_urlCompletionStarted = true; // flag for slotMatch()
3064 // kDebug(1202) << "Local Completion object found!";
3065 QString completion = m_pURLCompletion->makeCompletion( text );
3066 m_currentDir.clear();
3068 if ( completion.isNull() && !m_pURLCompletion->isRunning() )
3070 // No match() signal will come from m_pURLCompletion
3071 // ask the global one
3072 // tell the static completion object about the current completion mode
3073 completion = s_pCompletion->makeCompletion( text );
3075 // some special handling necessary for CompletionPopup
3076 if ( m_combo->completionMode() == KGlobalSettings::CompletionPopup ||
3077 m_combo->completionMode() == KGlobalSettings::CompletionPopupAuto )
3078 m_combo->setCompletedItems( historyPopupCompletionItems( text ) );
3080 else if ( !completion.isNull() )
3081 m_combo->setCompletedText( completion );
3083 else
3085 // To be continued in slotMatch()...
3086 if( !m_pURLCompletion->dir().isEmpty() )
3087 m_currentDir = m_pURLCompletion->dir();
3090 // kDebug(1202) << "Current dir:" << m_currentDir << "Current text:" << text;
3093 void KonqMainWindow::slotSubstringcompletion( const QString& text )
3095 QString currentURL = m_currentView->url().prettyUrl();
3096 bool filesFirst = currentURL.startsWith( '/' ) ||
3097 currentURL.startsWith( "file:/" );
3098 QStringList items;
3099 if ( filesFirst && m_pURLCompletion )
3100 items = m_pURLCompletion->substringCompletion( text );
3102 items += s_pCompletion->substringCompletion( text );
3103 if ( !filesFirst && m_pURLCompletion )
3104 items += m_pURLCompletion->substringCompletion( text );
3106 m_combo->setCompletedItems( items );
3109 void KonqMainWindow::slotRotation( KCompletionBase::KeyBindingType type )
3111 // Tell slotMatch() to do nothing
3112 m_urlCompletionStarted = false;
3114 bool prev = (type == KCompletionBase::PrevCompletionMatch);
3115 if ( prev || type == KCompletionBase::NextCompletionMatch ) {
3116 QString completion = prev ? m_pURLCompletion->previousMatch() :
3117 m_pURLCompletion->nextMatch();
3119 if( completion.isNull() ) { // try the history KCompletion object
3120 completion = prev ? s_pCompletion->previousMatch() :
3121 s_pCompletion->nextMatch();
3123 if ( completion.isEmpty() || completion == m_combo->currentText() )
3124 return;
3126 m_combo->setCompletedText( completion );
3130 // Handle match() from m_pURLCompletion
3131 void KonqMainWindow::slotMatch( const QString &match )
3133 if ( match.isEmpty() ) // this case is handled directly
3134 return;
3136 // Check flag to avoid match() raised by rotation
3137 if ( m_urlCompletionStarted ) {
3138 m_urlCompletionStarted = false;
3140 // some special handling necessary for CompletionPopup
3141 if ( m_combo->completionMode() == KGlobalSettings::CompletionPopup ||
3142 m_combo->completionMode() == KGlobalSettings::CompletionPopupAuto ) {
3143 QStringList items = m_pURLCompletion->allMatches();
3144 items += historyPopupCompletionItems( m_combo->currentText() );
3145 // items.sort(); // should we?
3146 m_combo->setCompletedItems( items );
3148 else if ( !match.isNull() )
3149 m_combo->setCompletedText( match );
3153 void KonqMainWindow::slotCtrlTabPressed()
3155 KonqView * view = m_pViewManager->chooseNextView( m_currentView );
3156 if ( view )
3157 m_pViewManager->setActivePart( view->part() );
3160 void KonqMainWindow::slotClearHistory()
3162 KonqHistoryManager::kself()->emitClear();
3165 void KonqMainWindow::slotClearComboHistory()
3167 if (m_combo && m_combo->count())
3168 m_combo->clearHistory();
3171 bool KonqMainWindow::eventFilter(QObject*obj,QEvent *ev)
3173 if ( ( ev->type()==QEvent::FocusIn || ev->type()==QEvent::FocusOut ) &&
3174 m_combo && m_combo->lineEdit() && m_combo == obj )
3176 //kDebug(1202) << obj << obj->metaObject()->className() << obj->name();
3178 QFocusEvent * focusEv = static_cast<QFocusEvent*>(ev);
3179 if (focusEv->reason() == Qt::PopupFocusReason)
3181 return KParts::MainWindow::eventFilter( obj, ev );
3184 KParts::BrowserExtension * ext = 0;
3185 if ( m_currentView )
3186 ext = m_currentView->browserExtension();
3188 const QMetaObject* slotMetaObject = 0;
3189 if (ext)
3190 slotMetaObject = ext->metaObject();
3192 if (ev->type()==QEvent::FocusIn)
3194 //kDebug(1202) << "ComboBox got the focus...";
3195 if (m_bLocationBarConnected)
3197 //kDebug(1202) << "Was already connected...";
3198 return KParts::MainWindow::eventFilter( obj, ev );
3200 m_bLocationBarConnected = true;
3202 // Workaround for Qt issue: usually, QLineEdit reacts on Ctrl-D,
3203 // but the duplicate_window action also has Ctrl-D as accel and
3204 // prevents the lineedit from getting this event. IMHO the accel
3205 // should be disabled in favor of the focus-widget.
3206 QAction *duplicate = actionCollection()->action("duplicate_window");
3207 if ( duplicate->shortcuts().contains( QKeySequence(Qt::CTRL+Qt::Key_D) ))
3208 duplicate->setEnabled( false );
3210 connect( m_paCut, SIGNAL( triggered() ), m_combo->lineEdit(), SLOT( cut() ) );
3211 connect( m_paCopy, SIGNAL( triggered() ), m_combo->lineEdit(), SLOT( copy() ) );
3212 connect( m_paPaste, SIGNAL( triggered() ), m_combo->lineEdit(), SLOT( paste() ) );
3213 connect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slotClipboardDataChanged()) );
3214 connect( m_combo->lineEdit(), SIGNAL(textChanged(const QString &)), this, SLOT(slotCheckComboSelection()) );
3215 connect( m_combo->lineEdit(), SIGNAL(selectionChanged()), this, SLOT(slotCheckComboSelection()) );
3217 slotClipboardDataChanged();
3219 else if ( ev->type()==QEvent::FocusOut)
3221 //kDebug(1202) << "ComboBox lost focus...";
3222 if (!m_bLocationBarConnected)
3224 //kDebug(1202) << "Was already disconnected...";
3225 return KParts::MainWindow::eventFilter( obj, ev );
3227 m_bLocationBarConnected = false;
3229 // see above in FocusIn for explanation
3230 // we use new_window as reference, as it's always in the same state
3231 // as duplicate_window
3232 QAction *duplicate = actionCollection()->action("duplicate_window");
3233 if ( duplicate->shortcuts().contains( QKeySequence(Qt::CTRL+Qt::Key_D) ) )
3234 duplicate->setEnabled( actionCollection()->action("new_window")->isEnabled() );
3236 disconnect( m_paCut, SIGNAL( triggered() ), m_combo->lineEdit(), SLOT( cut() ) );
3237 disconnect( m_paCopy, SIGNAL( triggered() ), m_combo->lineEdit(), SLOT( copy() ) );
3238 disconnect( m_paPaste, SIGNAL( triggered() ), m_combo->lineEdit(), SLOT( paste() ) );
3239 disconnect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slotClipboardDataChanged()) );
3240 disconnect( m_combo->lineEdit(), SIGNAL(textChanged(const QString &)), this, SLOT(slotCheckComboSelection()) );
3241 disconnect( m_combo->lineEdit(), SIGNAL(selectionChanged()), this, SLOT(slotCheckComboSelection()) );
3243 if ( ext )
3245 m_paCut->setEnabled( ext->isActionEnabled( "cut" ) );
3246 m_paCopy->setEnabled( ext->isActionEnabled( "copy" ) );
3247 m_paPaste->setEnabled( ext->isActionEnabled( "paste" ) );
3249 else
3251 m_paCut->setEnabled( false );
3252 m_paCopy->setEnabled( false );
3253 m_paPaste->setEnabled( false );
3257 return KParts::MainWindow::eventFilter( obj, ev );
3260 void KonqMainWindow::slotClipboardDataChanged()
3262 const QMimeData *data = QApplication::clipboard()->mimeData();
3263 m_paPaste->setEnabled( data->hasText() );
3264 slotCheckComboSelection();
3267 void KonqMainWindow::slotCheckComboSelection()
3269 bool hasSelection = m_combo->lineEdit()->hasSelectedText();
3270 //kDebug(1202) << "m_combo->lineEdit()->hasMarkedText():" << hasSelection;
3271 m_paCopy->setEnabled( hasSelection );
3272 m_paCut->setEnabled( hasSelection );
3275 void KonqMainWindow::slotClearLocationBar()
3277 slotStop();
3278 m_combo->clearTemporary();
3279 focusLocationBar();
3282 void KonqMainWindow::slotForceSaveMainWindowSettings()
3284 if ( autoSaveSettings() ) { // don't do it on e.g. JS window.open windows with no toolbars!
3285 saveAutoSaveSettings();
3289 void KonqMainWindow::slotShowMenuBar()
3291 if (menuBar()->isVisible())
3292 menuBar()->hide();
3293 else
3294 menuBar()->show();
3295 slotForceSaveMainWindowSettings();
3298 void KonqMainWindow::slotUpdateFullScreen( bool set )
3300 KToggleFullScreenAction::setFullScreen( this, set );
3301 if( set )
3303 // Create toolbar button for exiting from full-screen mode
3304 // ...but only if there isn't one already...
3306 bool haveFullScreenButton = false;
3308 //Walk over the toolbars and check whether there is a show fullscreen button in any of them
3309 foreach (KToolBar* bar, findChildren<KToolBar*>())
3311 //Are we plugged here, in a visible toolbar?
3312 if (bar->isVisible() &&
3313 action( "fullscreen" )->associatedWidgets().contains(bar))
3315 haveFullScreenButton = true;
3316 break;
3320 if (!haveFullScreenButton)
3322 QList<QAction*> lst;
3323 lst.append( m_ptaFullScreen );
3324 plugActionList( "fullscreen", lst );
3328 m_prevMenuBarVisible = menuBar()->isVisible();
3329 menuBar()->hide();
3330 m_paShowMenuBar->setChecked( false );
3332 // Qt bug, the flags are lost. They know about it.
3333 // happens only with the hackish non-_NET_WM_STATE_FULLSCREEN way
3334 setAttribute( Qt::WA_DeleteOnClose );
3335 // Qt bug (see below)
3336 //### KDE4: still relevant?
3337 #if 0
3338 setAcceptDrops( false );
3339 topData()->dnd = 0;
3340 setAcceptDrops( true );
3341 #endif
3343 else
3345 unplugActionList( "fullscreen" );
3347 if (m_prevMenuBarVisible)
3349 menuBar()->show();
3350 m_paShowMenuBar->setChecked( true );
3353 // Qt bug, the flags aren't restored. They know about it.
3354 //setWFlags( WType_TopLevel | WDestructiveClose );
3355 #ifdef __GNUC__
3356 #warning "Dunno how to port this, is the workaround still needed?"
3357 #endif
3358 // ( Qt::Window );
3359 setAttribute( Qt::WA_DeleteOnClose );
3361 #if 0 //### KDE4: is this still relevant?
3362 // Other Qt bug
3363 setAcceptDrops( false );
3364 topData()->dnd = 0;
3365 setAcceptDrops( true );
3366 #endif
3370 void KonqMainWindow::setLocationBarURL( const KUrl &url )
3372 setLocationBarURL( url.pathOrUrl() );
3375 void KonqMainWindow::setLocationBarURL( const QString &url )
3377 if (url != m_combo->lineEdit()->text()) {
3378 //kDebug(1202) << "url=" << url;
3379 m_combo->setURL( url );
3380 updateWindowIcon();
3384 void KonqMainWindow::setPageSecurity( PageSecurity pageSecurity )
3386 m_combo->setPageSecurity( pageSecurity );
3389 void KonqMainWindow::showPageSecurity()
3391 if ( m_currentView && m_currentView->part() ) {
3392 QAction *act = m_currentView->part()->action( "security" );
3393 if ( act )
3394 act->trigger();
3398 // Called via DBUS from KonquerorApplication
3399 void KonqMainWindow::comboAction( int action, const QString& url, const QString& senderId )
3401 if (!s_lstViews) // this happens in "konqueror --silent"
3402 return;
3404 KonqCombo *combo = 0;
3405 foreach ( KonqMainWindow* window, *s_lstViews ) {
3406 if ( window && window->m_combo ) {
3407 combo = window->m_combo;
3409 switch ( action ) {
3410 case ComboAdd:
3411 combo->insertPermanent( url );
3412 break;
3413 case ComboClear:
3414 combo->clearHistory();
3415 break;
3416 case ComboRemove:
3417 combo->removeURL( url );
3418 break;
3419 default:
3420 break;
3425 // only one instance should save...
3426 if ( combo && senderId == QDBusConnection::sessionBus().baseService() )
3427 combo->saveItems();
3430 QString KonqMainWindow::locationBarURL() const
3432 return m_combo->currentText();
3435 void KonqMainWindow::focusLocationBar()
3437 if ( m_combo->isVisible() || !isVisible() )
3438 m_combo->setFocus();
3441 void KonqMainWindow::startAnimation()
3443 m_paAnimatedLogo->start();
3444 m_paStop->setEnabled( true );
3447 void KonqMainWindow::stopAnimation()
3449 m_paAnimatedLogo->stop();
3450 m_paStop->setEnabled( false );
3453 void KonqMainWindow::setUpEnabled( const KUrl &url )
3455 bool bHasUpURL = ( (url.hasPath() && url.path() != "/" && url.path()[0] == '/')
3456 || !url.query().isEmpty() /*e.g. lists.kde.org*/ );
3457 if ( !bHasUpURL )
3458 bHasUpURL = url.hasSubUrl();
3460 m_paUp->setEnabled(bHasUpURL);
3464 int KonqMainWindow::maxThrobberHeight()
3466 // This comes from QMenuBar::sizeHint and QMenuBarPrivate::calcActionRects
3467 const QFontMetrics fm = menuBar()->fontMetrics();
3468 QSize sz(100, fm.height());
3469 //let the style modify the above size..
3470 QStyleOptionMenuItem opt;
3471 opt.fontMetrics = fm;
3472 opt.state = QStyle::State_Enabled;
3473 opt.menuRect = menuBar()->rect();
3474 opt.text = "dummy";
3475 sz = menuBar()->style()->sizeFromContents(QStyle::CT_MenuBarItem, &opt, sz, menuBar());
3476 //kDebug() << "maxThrobberHeight=" << sz.height();
3477 return sz.height();
3480 void KonqMainWindow::setAnimatedLogoSize()
3482 const int buttonHeight = maxThrobberHeight();
3483 // This gives the best results: we force a bigger icon size onto the style, and it'll just have to eat up its margin.
3484 // So we don't need to ask sizeFromContents at all.
3485 int iconSize = buttonHeight;
3486 #if 0
3487 QStyleOptionToolButton opt;
3488 opt.initFrom(m_paAnimatedLogo);
3489 const QSize finalSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, opt.iconSize, m_paAnimatedLogo);
3490 //kDebug() << "throbberIconSize=" << buttonHeight << "-" << finalSize.height() - opt.iconSize.height();
3491 int iconSize = buttonHeight - (finalSize.height() - opt.iconSize.height());
3492 #endif
3494 m_paAnimatedLogo->setFixedSize(QSize(buttonHeight, buttonHeight));
3496 //kDebug() << "buttonHeight=" << buttonHeight << "max iconSize=" << iconSize;
3497 if ( iconSize < KIconLoader::SizeSmallMedium )
3498 iconSize = KIconLoader::SizeSmall;
3499 else if ( iconSize < KIconLoader::SizeMedium )
3500 iconSize = KIconLoader::SizeSmallMedium;
3501 else if ( iconSize < KIconLoader::SizeLarge )
3502 iconSize = KIconLoader::SizeMedium ;
3503 else if ( iconSize < KIconLoader::SizeHuge )
3504 iconSize = KIconLoader::SizeLarge;
3505 //kDebug() << "final iconSize=" << iconSize;
3506 m_paAnimatedLogo->setIconSize(QSize(iconSize, iconSize));
3509 void KonqMainWindow::initActions()
3511 // Note about this method : don't call setEnabled() on any of the actions.
3512 // They are all disabled then re-enabled with enableAllActions
3513 // If any one needs to be initially disabled, put that code in enableAllActions
3515 // For the popup menu only.
3516 m_pMenuNew = new KNewMenu(actionCollection(), this, "new_menu");
3518 // File menu
3520 KAction* action = actionCollection()->addAction("new_window");
3521 action->setIcon(KIcon("window-new"));
3522 action->setText(i18n( "New &Window" ));
3523 connect(action, SIGNAL(triggered()), SLOT( slotNewWindow() ));
3524 action->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::New));
3525 action = actionCollection()->addAction("duplicate_window");
3526 action->setIcon(KIcon("window-duplicate"));
3527 action->setText(i18n( "&Duplicate Window" ));
3528 connect(action, SIGNAL(triggered()), SLOT( slotDuplicateWindow() ));
3529 action->setShortcut(Qt::CTRL+Qt::Key_D);
3530 action = actionCollection()->addAction("sendURL");
3531 action->setIcon(KIcon("mail-message-new"));
3532 action->setText(i18n( "Send &Link Address..." ));
3533 connect(action, SIGNAL(triggered()), SLOT( slotSendURL() ));
3534 action = actionCollection()->addAction("sendPage");
3535 action->setIcon(KIcon("mail-message-new"));
3536 action->setText(i18n( "S&end File..." ));
3537 connect(action, SIGNAL(triggered()), SLOT( slotSendFile() ));
3538 action = actionCollection()->addAction("open_location");
3539 action->setIcon(KIcon("document-open-remote"));
3540 action->setText(i18n( "&Open Location" ));
3541 action->setShortcut(Qt::ALT+Qt::Key_O);
3542 connect(action, SIGNAL(triggered()), SLOT( slotOpenLocation() ));
3544 action = actionCollection()->addAction("open_file");
3545 action->setIcon(KIcon("document-open"));
3546 action->setText(i18n( "&Open File..." ));
3547 connect(action, SIGNAL(triggered()), SLOT( slotOpenFile() ));
3548 action->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Open));
3550 #if 0
3551 m_paFindFiles = new KToggleAction(KIcon("edit-find"), i18n( "&Find File..." ), this);
3552 actionCollection()->addAction( "findfile", m_paFindFiles );
3553 connect(m_paFindFiles, SIGNAL(triggered() ), SLOT( slotToolFind() ));
3554 m_paFindFiles->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Find));
3555 #endif
3557 m_paPrint = actionCollection()->addAction( KStandardAction::Print, "print", 0, 0 );
3558 actionCollection()->addAction( KStandardAction::Quit, "quit", this, SLOT( close() ) );
3560 m_ptaUseHTML = new KToggleAction( i18n( "&Use index.html" ), this );
3561 actionCollection()->addAction( "usehtml", m_ptaUseHTML );
3562 connect(m_ptaUseHTML, SIGNAL(triggered() ), SLOT( slotShowHTML() ));
3563 m_paLockView = new KToggleAction( i18n( "Lock to Current Location"), this );
3564 actionCollection()->addAction( "lock", m_paLockView );
3565 connect(m_paLockView, SIGNAL(triggered() ), SLOT( slotLockView() ));
3566 m_paLinkView = new KToggleAction( i18nc( "This option links konqueror views", "Lin&k View"), this );
3567 actionCollection()->addAction( "link", m_paLinkView );
3568 connect(m_paLinkView, SIGNAL(triggered() ), SLOT( slotLinkView() ));
3570 // Go menu
3571 m_paUp = new KToolBarPopupAction( KIcon("go-up"), i18n( "&Up" ), this );
3572 actionCollection()->addAction( "go_up", m_paUp );
3573 m_paUp->setShortcuts( KStandardShortcut::shortcut(KStandardShortcut::Up) );
3574 connect( m_paUp, SIGNAL( triggered( Qt::MouseButtons, Qt::KeyboardModifiers) ), this,
3575 SLOT( slotUp(Qt::MouseButtons, Qt::KeyboardModifiers) ) );
3576 connect( m_paUp->menu(), SIGNAL( aboutToShow() ), this, SLOT( slotUpAboutToShow() ) );
3577 connect( m_paUp->menu(), SIGNAL(triggered(QAction *)), this, SLOT(slotUpActivated(QAction*)) );
3579 QPair< KGuiItem, KGuiItem > backForward = KStandardGuiItem::backAndForward();
3582 // Trash bin of closed tabs
3583 m_paClosedItems = new KToolBarPopupAction( KIcon("edit-undo-closed-tabs"), i18n( "Closed Items" ), this );
3584 actionCollection()->addAction( "closeditems", m_paClosedItems );
3585 m_closedItemsGroup = new QActionGroup(m_paClosedItems->menu());
3587 // set the closed tabs list shown
3588 connect( m_paClosedItems, SIGNAL(triggered()), m_pUndoManager, SLOT(undoLastClosedItem()) );
3589 connect( m_paClosedItems->menu(), SIGNAL(aboutToShow()), this, SLOT(slotClosedItemsListAboutToShow()) );
3590 connect( m_closedItemsGroup, SIGNAL(triggered(QAction*)), m_pUndoManager, SLOT(slotClosedItemsActivated(QAction*)) );
3591 connect( m_pViewManager, SIGNAL(aboutToRemoveTab(KonqFrameBase*)), this, SLOT(slotAddClosedUrl(KonqFrameBase*)) );
3592 connect( m_pUndoManager, SIGNAL(openClosedTab(const KonqClosedTabItem&)), m_pViewManager, SLOT(openClosedTab(const KonqClosedTabItem&)) );
3593 connect( m_pUndoManager, SIGNAL(openClosedWindow(const KonqClosedWindowItem&)), m_pViewManager, SLOT(openClosedWindow(const KonqClosedWindowItem&)) );
3594 connect( m_pUndoManager, SIGNAL(closedItemsListChanged()), this, SLOT(updateClosedItemsAction()));
3597 m_paSessions = new KActionMenu( i18n( "Sessions" ), this );
3598 actionCollection()->addAction( "sessions", m_paSessions );
3599 m_sessionsGroup = new QActionGroup(m_paSessions->menu());
3600 connect( m_paSessions->menu(), SIGNAL(aboutToShow()), this, SLOT(slotSessionsListAboutToShow()) );
3601 connect( m_sessionsGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotSessionActivated(QAction*)) );
3603 m_paBack = new KToolBarPopupAction( KIcon(backForward.first.iconName()), backForward.first.text(), this );
3604 actionCollection()->addAction( "go_back", m_paBack );
3605 m_paBack->setShortcuts( KStandardShortcut::shortcut(KStandardShortcut::Back) );
3606 connect( m_paBack, SIGNAL( triggered( Qt::MouseButtons, Qt::KeyboardModifiers) ), this,
3607 SLOT( slotBack(Qt::MouseButtons, Qt::KeyboardModifiers) ) );
3608 connect( m_paBack->menu(), SIGNAL( aboutToShow() ), this, SLOT( slotBackAboutToShow() ) );
3609 connect( m_paBack->menu(), SIGNAL(triggered(QAction*)), this, SLOT(slotBackActivated(QAction *)) );
3611 m_paForward = new KToolBarPopupAction( KIcon(backForward.second.iconName()), backForward.second.text(), this );
3612 actionCollection()->addAction( "go_forward", m_paForward );
3613 m_paForward->setShortcuts( KStandardShortcut::shortcut(KStandardShortcut::Forward) );
3614 connect( m_paForward, SIGNAL( triggered( Qt::MouseButtons, Qt::KeyboardModifiers) ), this,
3615 SLOT( slotForward(Qt::MouseButtons, Qt::KeyboardModifiers) ) );
3616 connect( m_paForward->menu(), SIGNAL( aboutToShow() ), this, SLOT( slotForwardAboutToShow() ) );
3617 connect( m_paForward->menu(), SIGNAL(triggered(QAction*)), this, SLOT(slotForwardActivated(QAction *)) );
3619 m_paHome = actionCollection()->addAction( KStandardAction::Home );
3620 m_paHome->setEnabled( true );
3621 connect( m_paHome, SIGNAL( triggered( Qt::MouseButtons, Qt::KeyboardModifiers) ), this,
3622 SLOT( slotHome(Qt::MouseButtons, Qt::KeyboardModifiers) ) );
3624 KonqMostOftenURLSAction *mostOften = new KonqMostOftenURLSAction( i18nc("@action:inmenu Go", "Most Often Visited"), this );
3625 actionCollection()->addAction( "go_most_often", mostOften );
3626 connect(mostOften, SIGNAL(activated(KUrl)), SLOT(slotOpenURL(KUrl)));
3628 action = new KonqHistoryAction(i18nc("@action:inmenu Go", "Recently Visited"), this);
3629 actionCollection()->addAction("history", action);
3630 connect(action, SIGNAL(activated(KUrl)), SLOT(slotOpenURL(KUrl)));
3632 action = actionCollection()->addAction("go_history");
3633 action->setIcon(KIcon("view-history"));
3634 action->setText(i18nc("@action:inmenu Go", "Show History in Sidebar"));
3635 connect(action, SIGNAL(triggered()), SLOT(slotGoHistory()));
3637 // Settings menu
3639 m_paSaveViewProfile = actionCollection()->addAction( "saveviewprofile" );
3640 m_paSaveViewProfile->setText( i18n( "&Save View Profile..." ) );
3641 connect(m_paSaveViewProfile, SIGNAL(triggered() ), SLOT( slotSaveViewProfile() ));
3643 // This list is just for the call to authorizeControlModule; see slotConfigure for the real code
3644 QStringList configureModules;
3645 configureModules << "khtml_general" << "bookmarks" <<
3646 "filebehavior" << "filetypes" << "kcmtrash" <<
3647 "khtml_appearance" << "khtml_behavior" << "khtml_java_js" <<
3648 "khtml_filter" << "ebrowsing" <<
3649 "kcmhistory" << "cookies" <<
3650 "cache" << "proxy" <<
3651 "crypto" << "useragent" <<
3652 "khtml_plugins" << "kcmkonqyperformance";
3654 if (!KAuthorized::authorizeControlModules(configureModules).isEmpty())
3655 actionCollection()->addAction( KStandardAction::Preferences, this, SLOT(slotConfigure()) );
3657 actionCollection()->addAction( KStandardAction::KeyBindings, guiFactory(), SLOT( configureShortcuts() ) );
3658 actionCollection()->addAction( KStandardAction::ConfigureToolbars, this, SLOT( slotConfigureToolbars() ) );
3660 m_paConfigureExtensions = actionCollection()->addAction("options_configure_extensions");
3661 m_paConfigureExtensions->setText( i18n("Configure Extensions...") );
3662 connect(m_paConfigureExtensions, SIGNAL(triggered() ), SLOT( slotConfigureExtensions()));
3663 m_paConfigureSpellChecking = actionCollection()->addAction("configurespellcheck");
3664 m_paConfigureSpellChecking->setIcon(KIcon("tools-check-spelling"));
3665 m_paConfigureSpellChecking->setText(i18n("Configure Spell Checking..."));
3666 connect(m_paConfigureSpellChecking, SIGNAL(triggered()), SLOT( slotConfigureSpellChecking()));
3668 // Window menu
3669 m_paSplitViewHor = actionCollection()->addAction("splitviewh");
3670 m_paSplitViewHor->setIcon( KIcon("view-split-left-right") );
3671 m_paSplitViewHor->setText( i18n( "Split View &Left/Right" ) );
3672 connect(m_paSplitViewHor, SIGNAL(triggered()), SLOT( slotSplitViewHorizontal() ));
3673 m_paSplitViewHor->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_L);
3674 m_paSplitViewVer = actionCollection()->addAction("splitviewv");
3675 m_paSplitViewVer->setIcon( KIcon("view-split-top-bottom") );
3676 m_paSplitViewVer->setText( i18n( "Split View &Top/Bottom" ) );
3677 connect(m_paSplitViewVer, SIGNAL(triggered()), SLOT( slotSplitViewVertical() ));
3678 m_paSplitViewVer->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_T);
3679 m_paAddTab = actionCollection()->addAction("newtab");
3680 m_paAddTab->setIcon( KIcon("tab-new") );
3681 m_paAddTab->setText( i18n( "&New Tab" ) );
3682 connect(m_paAddTab, SIGNAL(triggered()), SLOT( slotAddTab() ));
3683 m_paAddTab->setShortcuts(KShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_N, Qt::CTRL+Qt::Key_T));
3685 m_paDuplicateTab = actionCollection()->addAction("duplicatecurrenttab");
3686 m_paDuplicateTab->setIcon( KIcon("tab-duplicate") );
3687 m_paDuplicateTab->setText( i18n( "&Duplicate Current Tab" ) );
3688 connect(m_paDuplicateTab, SIGNAL(triggered()), SLOT( slotDuplicateTab() ));
3689 m_paDuplicateTab->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_D);
3690 m_paBreakOffTab = actionCollection()->addAction("breakoffcurrenttab");
3691 m_paBreakOffTab->setIcon( KIcon("tab-detach") );
3692 m_paBreakOffTab->setText( i18n( "Detach Current Tab" ) );
3693 connect(m_paBreakOffTab, SIGNAL(triggered()), SLOT( slotBreakOffTab() ));
3694 m_paBreakOffTab->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_B);
3695 m_paRemoveView = actionCollection()->addAction("removeview");
3696 m_paRemoveView->setIcon( KIcon("view-close") );
3697 m_paRemoveView->setText( i18n( "&Close Active View" ) );
3698 connect(m_paRemoveView, SIGNAL(triggered()), SLOT( slotRemoveView() ));
3699 m_paRemoveView->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_R);
3700 m_paRemoveTab = actionCollection()->addAction("removecurrenttab");
3701 m_paRemoveTab->setIcon( KIcon("tab-close") );
3702 m_paRemoveTab->setText( i18n( "Close Current Tab" ) );
3703 connect(m_paRemoveTab, SIGNAL(triggered()), SLOT( slotRemoveTab() ));
3704 m_paRemoveTab->setShortcut(Qt::CTRL+Qt::Key_W);
3705 m_paRemoveTab->setAutoRepeat(false);
3706 m_paRemoveOtherTabs = actionCollection()->addAction("removeothertabs");
3707 m_paRemoveOtherTabs->setIcon( KIcon("tab-close-other") );
3708 m_paRemoveOtherTabs->setText( i18n( "Close &Other Tabs" ) );
3709 connect(m_paRemoveOtherTabs, SIGNAL(triggered()), SLOT( slotRemoveOtherTabs() ));
3711 m_paActivateNextTab = actionCollection()->addAction("activatenexttab");
3712 m_paActivateNextTab->setText( i18n( "Activate Next Tab" ) );
3713 connect(m_paActivateNextTab, SIGNAL(triggered()), SLOT( slotActivateNextTab() ));
3714 m_paActivateNextTab->setShortcuts(QApplication::isRightToLeft() ? KStandardShortcut::tabPrev() : KStandardShortcut::tabNext());
3715 m_paActivatePrevTab = actionCollection()->addAction("activateprevtab");
3716 m_paActivatePrevTab->setText( i18n( "Activate Previous Tab" ) );
3717 connect(m_paActivatePrevTab, SIGNAL(triggered()), SLOT( slotActivatePrevTab() ));
3718 m_paActivatePrevTab->setShortcuts(QApplication::isRightToLeft() ? KStandardShortcut::tabNext() : KStandardShortcut::tabPrev());
3720 QString actionname;
3721 for (int i=1;i<13;i++) {
3722 actionname.sprintf("activate_tab_%02d", i);
3723 QAction *action = actionCollection()->addAction( actionname );
3724 action->setText( i18n("Activate Tab %1", i) );
3725 connect(action, SIGNAL(triggered()), SLOT(slotActivateTab()));
3728 m_paMoveTabLeft = actionCollection()->addAction("tab_move_left");
3729 m_paMoveTabLeft->setText( i18n("Move Tab Left") );
3730 m_paMoveTabLeft->setIcon( KIcon("tab-move-left") );
3731 connect(m_paMoveTabLeft, SIGNAL(triggered()), SLOT( slotMoveTabLeft()));
3732 m_paMoveTabLeft->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_Left);
3733 m_paMoveTabRight = actionCollection()->addAction("tab_move_right");
3734 m_paMoveTabRight->setText( i18n("Move Tab Right") );
3735 m_paMoveTabRight->setIcon( KIcon("tab-move-right") );
3736 connect(m_paMoveTabRight, SIGNAL(triggered()), SLOT( slotMoveTabRight()));
3737 m_paMoveTabRight->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_Right);
3739 #ifndef NDEBUG
3740 action = actionCollection()->addAction("dumpdebuginfo");
3741 action->setIcon( KIcon("view-dump-debug-info") );
3742 action->setText( i18n( "Dump Debug Info" ) );
3743 connect(action, SIGNAL(triggered()), SLOT( slotDumpDebugInfo() ));
3744 #endif
3746 m_paSaveRemoveViewProfile = actionCollection()->addAction("saveremoveviewprofile" );
3747 m_paSaveRemoveViewProfile->setText( i18n( "C&onfigure View Profiles..." ) );
3748 connect(m_paSaveRemoveViewProfile, SIGNAL(triggered() ), m_pViewManager, SLOT( slotProfileDlg() ));
3749 m_pamLoadViewProfile = new KActionMenu( i18n( "Load &View Profile" ), this );
3750 actionCollection()->addAction( "loadviewprofile", m_pamLoadViewProfile );
3752 m_pViewManager->setProfiles( m_pamLoadViewProfile );
3754 m_ptaFullScreen = KStandardAction::fullScreen( 0, 0, this, this );
3755 actionCollection()->addAction( m_ptaFullScreen->objectName(), m_ptaFullScreen );
3756 KShortcut fullScreenShortcut = m_ptaFullScreen->shortcut();
3757 fullScreenShortcut.setAlternate( Qt::Key_F11 );
3758 m_ptaFullScreen->setShortcut( fullScreenShortcut );
3759 connect( m_ptaFullScreen, SIGNAL( toggled( bool )), this, SLOT( slotUpdateFullScreen( bool )));
3761 KShortcut reloadShortcut = KStandardShortcut::shortcut(KStandardShortcut::Reload);
3762 reloadShortcut.setAlternate(Qt::CTRL + Qt::Key_R);
3763 m_paReload = actionCollection()->addAction("reload");
3764 m_paReload->setIcon( KIcon("view-refresh") );
3765 m_paReload->setText( i18n( "&Reload" ) );
3766 connect(m_paReload, SIGNAL(triggered()), SLOT( slotReload() ));
3767 m_paReload->setShortcuts(reloadShortcut);
3768 m_paReloadAllTabs = actionCollection()->addAction("reload_all_tabs");
3769 m_paReloadAllTabs->setIcon( KIcon("view-refresh-all") );
3770 m_paReloadAllTabs->setText( i18n( "&Reload All Tabs" ) );
3771 connect(m_paReloadAllTabs, SIGNAL(triggered()), SLOT( slotReloadAllTabs() ));
3772 m_paReloadAllTabs->setShortcut(Qt::SHIFT+Qt::Key_F5);
3773 // "Forced"/ "Hard" reload action - re-downloads all e.g. images even if a cached
3774 // version already exists.
3775 m_paForceReload = actionCollection()->addAction("hard_reload");
3776 // TODO - request new icon? (view-refresh will do for the time being)
3777 m_paForceReload->setIcon( KIcon("view-refresh") );
3778 m_paForceReload->setText( i18n( "&Force Reload" ) );
3779 connect(m_paForceReload, SIGNAL(triggered()), SLOT( slotForceReload()));
3780 m_paForceReload->setShortcuts(KShortcut(Qt::CTRL+Qt::Key_F5, Qt::CTRL+Qt::SHIFT+Qt::Key_R));
3782 m_paUndo = KStandardAction::undo( m_pUndoManager, SLOT( undo() ), this );
3783 actionCollection()->addAction( "undo", m_paUndo );
3784 connect( m_pUndoManager, SIGNAL( undoTextChanged(QString) ),
3785 this, SLOT( slotUndoTextChanged(QString) ) );
3787 // Those are connected to the browserextension directly
3788 m_paCut = KStandardAction::cut( 0, 0, this );
3789 actionCollection()->addAction( "cut", m_paCut );
3790 KShortcut cutShortCut( m_paCut->shortcut() );
3791 cutShortCut.remove( Qt::SHIFT + Qt::Key_Delete ); // used for deleting files
3792 m_paCut->setShortcuts( cutShortCut );
3794 m_paCopy = KStandardAction::copy( 0, 0, this );
3795 actionCollection()->addAction( "copy", m_paCopy );
3796 m_paPaste = KStandardAction::paste( 0, 0, this );
3797 actionCollection()->addAction( "paste", m_paPaste );
3798 m_paStop = actionCollection()->addAction("stop");
3799 m_paStop->setIcon( KIcon("process-stop") );
3800 m_paStop->setText( i18n( "&Stop" ) );
3801 connect(m_paStop, SIGNAL(triggered()), SLOT( slotStop() ));
3802 m_paStop->setShortcut(Qt::Key_Escape);
3804 m_paAnimatedLogo = new KAnimatedButton( this );
3805 m_paAnimatedLogo->setAutoRaise(true);
3806 m_paAnimatedLogo->setFocusPolicy(Qt::NoFocus);
3807 m_paAnimatedLogo->setToolButtonStyle(Qt::ToolButtonIconOnly);
3808 setAnimatedLogoSize();
3809 m_paAnimatedLogo->setIcons("process-working-kde");
3810 menuBar()->setCornerWidget(m_paAnimatedLogo);
3812 // Location bar
3813 m_locationLabel = new KonqDraggableLabel( this, i18n("L&ocation: ") );
3814 KAction *locationAction = new KAction( this );
3815 actionCollection()->addAction( "location_label", locationAction );
3816 locationAction->setText( i18n("L&ocation: ") );
3817 connect(locationAction, SIGNAL(triggered()), SLOT( slotLocationLabelActivated() ));
3818 locationAction->setDefaultWidget(m_locationLabel);
3819 m_locationLabel->setBuddy( m_combo );
3821 KAction *comboAction = new KAction( this );
3822 actionCollection()->addAction( "toolbar_url_combo", comboAction );
3823 comboAction->setText( i18n( "Location Bar" ) );
3824 comboAction->setShortcut(Qt::Key_F6);
3825 connect(comboAction, SIGNAL(triggered()), SLOT( slotLocationLabelActivated() ));
3826 comboAction->setDefaultWidget(m_combo);
3827 comboAction->setShortcutConfigurable( false );
3829 m_combo->setWhatsThis( i18n( "<html>Location Bar<br /><br />Enter a web address or search term.</html>" ) );
3831 KAction *clearLocation = actionCollection()->addAction("clear_location");
3832 clearLocation->setIcon( KIcon(QApplication::isRightToLeft() ? "edit-clear-locationbar-rtl" : "edit-clear-locationbar-ltr") );
3833 clearLocation->setText( i18n( "Clear Location Bar" ) );
3834 clearLocation->setShortcut(Qt::CTRL+Qt::Key_L);
3835 connect( clearLocation, SIGNAL( triggered() ),
3836 SLOT( slotClearLocationBar() ) );
3837 clearLocation->setWhatsThis( i18n( "<html>Clear Location bar<br /><br />"
3838 "Clears the contents of the location bar.</html>" ) );
3840 // Bookmarks menu
3841 m_pamBookmarks = new KBookmarkActionMenu(s_bookmarkManager->root(),
3842 i18n( "&Bookmarks" ), this);
3843 actionCollection()->addAction( "bookmarks", m_pamBookmarks );
3845 // The actual menu needs a different action collection, so that the bookmarks
3846 // don't appear in kedittoolbar
3847 m_bookmarksActionCollection = new KActionCollection( static_cast<QWidget*>( this ) );
3849 m_pBookmarkMenu = new KonqBookmarkMenu( s_bookmarkManager, m_pBookmarksOwner, m_pamBookmarks, m_bookmarksActionCollection );
3851 QAction *addBookmark = actionCollection()->action("add_bookmark");
3852 if (addBookmark)
3853 addBookmark->setText(i18n("Bookmark This Location"));
3855 m_paShowMenuBar = KStandardAction::showMenubar( this, SLOT( slotShowMenuBar() ), this );
3856 actionCollection()->addAction( KStandardAction::name(KStandardAction::ShowMenubar), m_paShowMenuBar );
3858 action = actionCollection()->addAction( "konqintro" );
3859 action->setText( i18n( "Kon&queror Introduction" ) );
3860 connect(action, SIGNAL(triggered() ), SLOT( slotIntro() ));
3862 QAction *goUrl = actionCollection()->addAction("go_url");
3863 goUrl->setIcon( KIcon("go-jump-locationbar") );
3864 goUrl->setText( i18n( "Go" ) );
3865 connect(goUrl, SIGNAL(triggered()), SLOT( goURL() ));
3866 goUrl->setWhatsThis( i18n( "<html>Go<br /><br />"
3867 "Goes to the page that has been entered into the location bar.</html>" ) );
3869 enableAllActions( false );
3871 // help stuff
3872 m_paUp->setWhatsThis( i18n( "<html>Enter the parent folder<br /><br />"
3873 "For instance, if the current location is file:/home/%1 clicking this "
3874 "button will take you to file:/home.</html>" , KUser().loginName() ) );
3875 m_paUp->setToolTip( i18n( "Enter the parent folder" ) );
3877 m_paBack->setWhatsThis( i18n( "Move backwards one step in the browsing history" ) );
3878 m_paBack->setToolTip( i18n( "Move backwards one step in the browsing history" ) );
3880 m_paForward->setWhatsThis( i18n( "Move forward one step in the browsing history" ) );
3881 m_paForward->setToolTip( i18n( "Move forward one step in the browsing history" ) );
3884 m_paClosedItems->setWhatsThis( i18n( "Move backwards one step in the closed tabs history" ) );
3885 m_paClosedItems->setToolTip( i18n( "Move backwards one step in the closed tabs history" ) );
3888 m_paReload->setWhatsThis( i18n( "<html>Reload the currently displayed document<br /><br />"
3889 "This may, for example, be needed to refresh web pages that have been "
3890 "modified since they were loaded, in order to make the changes visible.</html>" ) );
3891 m_paReload->setToolTip( i18n( "Reload the currently displayed document" ) );
3893 m_paReloadAllTabs->setWhatsThis( i18n( "<html>Reload all currently displayed documents in tabs<br /><br />"
3894 "This may, for example, be needed to refresh web pages that have been "
3895 "modified since they were loaded, in order to make the changes visible.</html>" ) );
3896 m_paReloadAllTabs->setToolTip( i18n( "Reload all currently displayed document in tabs" ) );
3898 m_paStop->setWhatsThis( i18n( "<html>Stop loading the document<br /><br />"
3899 "All network transfers will be stopped and Konqueror will display the content "
3900 "that has been received so far.</html>" ) );
3902 m_paForceReload->setWhatsThis( i18n( "<html>Reload the currently displayed document<br /><br />"
3903 "This may, for example, be needed to refresh web pages that have been "
3904 "modified since they were loaded, in order to make the changes visible. Any images on the page are downloaded again, even if cached copies exist.</html>" ) );
3906 m_paForceReload->setToolTip( i18n( "Force a reload of the currently displayed document and any contained images" ) );
3909 m_paStop->setToolTip( i18n( "Stop loading the document" ) );
3911 m_paCut->setWhatsThis( i18n( "<html>Cut the currently selected text or item(s) and move it "
3912 "to the system clipboard<br /><br />"
3913 "This makes it available to the <b>Paste</b> command in Konqueror "
3914 "and other KDE applications.</html>" ) );
3915 m_paCut->setToolTip( i18n( "Move the selected text or item(s) to the clipboard" ) );
3917 m_paCopy->setWhatsThis( i18n( "<html>Copy the currently selected text or item(s) to the "
3918 "system clipboard<br /><br />"
3919 "This makes it available to the <b>Paste</b> command in Konqueror "
3920 "and other KDE applications.</html>" ) );
3921 m_paCopy->setToolTip( i18n( "Copy the selected text or item(s) to the clipboard" ) );
3923 m_paPaste->setWhatsThis( i18n( "<html>Paste the previously cut or copied clipboard "
3924 "contents<br /><br />"
3925 "This also works for text copied or cut from other KDE applications.</html>" ) );
3926 m_paPaste->setToolTip( i18n( "Paste the clipboard contents" ) );
3928 m_paPrint->setWhatsThis( i18n( "<html>Print the currently displayed document<br /><br />"
3929 "You will be presented with a dialog where you can set various "
3930 "options, such as the number of copies to print and which printer "
3931 "to use.<br /><br />"
3932 "This dialog also provides access to special KDE printing "
3933 "services such as creating a PDF file from the current document.</html>" ) );
3934 m_paPrint->setToolTip( i18n( "Print the current document" ) );
3938 // Please proof-read those (David)
3940 m_ptaUseHTML->setToolTip( i18n("If present, open index.html when entering a folder.") );
3941 m_paLockView->setToolTip( i18n("A locked view cannot change folders. Use in combination with 'link view' to explore many files from one folder") );
3942 m_paLinkView->setToolTip( i18n("Sets the view as 'linked'. A linked view follows folder changes made in other linked views.") );
3945 void KonqExtendedBookmarkOwner::openBookmark(const KBookmark & bm, Qt::MouseButtons mb, Qt::KeyboardModifiers km)
3947 kDebug(1202) << bm.url() << km << mb;
3949 const QString url = bm.url().url();
3951 KonqOpenURLRequest req;
3952 req.browserArgs.setNewTab(true);
3953 req.newTabInFront = KonqSettings::newTabsInFront();
3954 req.forceAutoEmbed = true;
3956 if (km & Qt::ShiftModifier) {
3957 req.newTabInFront = !req.newTabInFront;
3960 if( km & Qt::ControlModifier ) { // Ctrl Left/MMB
3961 m_pKonqMainWindow->openFilteredUrl( url, req);
3962 } else if( mb & Qt::MidButton ) {
3963 if(KonqSettings::mmbOpensTab()) {
3964 m_pKonqMainWindow->openFilteredUrl( url, req);
3965 } else {
3966 KUrl finalURL = KonqMisc::konqFilteredURL( m_pKonqMainWindow, url );
3967 KonqMisc::createNewWindow( finalURL );
3970 else {
3971 m_pKonqMainWindow->openFilteredUrl( url, false );
3975 void KonqMainWindow::slotMoveTabLeft()
3977 if ( QApplication::isRightToLeft() )
3978 m_pViewManager->moveTabForward();
3979 else
3980 m_pViewManager->moveTabBackward();
3982 updateViewActions();
3985 void KonqMainWindow::slotMoveTabRight()
3987 if ( QApplication::isRightToLeft() )
3988 m_pViewManager->moveTabBackward();
3989 else
3990 m_pViewManager->moveTabForward();
3992 updateViewActions();
3995 void KonqMainWindow::updateHistoryActions()
3997 if(m_currentView)
3999 m_paBack->setEnabled( m_currentView->canGoBack() );
4000 m_paForward->setEnabled( m_currentView->canGoForward() );
4004 void KonqMainWindow::updateToolBarActions( bool pendingAction /*=false*/)
4006 // Enables/disables actions that depend on the current view & url (mostly toolbar)
4007 // Up, back, forward, the edit extension, stop button, wheel
4008 setUpEnabled( m_currentView->url() );
4009 m_paBack->setEnabled( m_currentView->canGoBack() );
4010 m_paForward->setEnabled( m_currentView->canGoForward() );
4012 if ( m_currentView->isLoading() )
4014 startAnimation(); // takes care of m_paStop
4016 else
4018 m_paAnimatedLogo->stop();
4019 m_paStop->setEnabled( pendingAction ); //enable/disable based on any pending actions...
4022 if ( m_currentView && m_currentView->url().isLocalFile() &&
4023 !m_currentView->isLockedViewMode() ) {
4024 if (m_currentView->showsDirectory())
4025 m_ptaUseHTML->setEnabled( true );
4026 else if ( m_currentView->serviceTypes().contains("text/html") ) {
4027 // Currently viewing an index.html file via this feature (i.e. url points to a dir)
4028 QString locPath = KUrl( m_currentView->locationBarURL() ).path();
4029 m_ptaUseHTML->setEnabled( QFileInfo( locPath ).isDir() );
4030 } else
4031 m_ptaUseHTML->setEnabled( false );
4033 else
4035 m_ptaUseHTML->setEnabled( false );
4039 void KonqMainWindow::updateViewActions()
4041 // Update actions that depend on the current view and its mode, or on the number of views etc.
4043 // Don't do things in this method that depend on m_currentView->url().
4044 // When going 'back' in history this will be called before opening the url.
4045 // Use updateToolBarActions instead.
4047 bool enable = false;
4049 if ( m_currentView && m_currentView->part() )
4051 // Avoid qWarning from QObject::property if it doesn't exist
4052 if ( m_currentView->part()->metaObject()->indexOfProperty( "supportsUndo" ) != -1 )
4054 QVariant prop = m_currentView->part()->property( "supportsUndo" );
4055 if ( prop.isValid() && prop.toBool() )
4056 enable = true;
4060 m_pUndoManager->updateSupportsFileUndo(enable);
4062 // slotUndoAvailable( m_pUndoManager->undoAvailable() );
4064 m_paLockView->setEnabled( true );
4065 m_paLockView->setChecked( m_currentView && m_currentView->isLockedLocation() );
4067 // Can remove view if we'll still have a main view after that
4068 m_paRemoveView->setEnabled( mainViewsCount() > 1 ||
4069 ( m_currentView && m_currentView->isToggleView() ) );
4071 if ( !currentView() || !currentView()->frame())
4073 m_paAddTab->setEnabled( false );
4074 m_paDuplicateTab->setEnabled( false );
4075 m_paRemoveTab->setEnabled( false );
4076 m_paRemoveOtherTabs->setEnabled( false );
4077 m_paBreakOffTab->setEnabled( false );
4078 m_paActivateNextTab->setEnabled( false );
4079 m_paActivatePrevTab->setEnabled( false );
4080 m_paMoveTabLeft->setEnabled( false );
4081 m_paMoveTabRight->setEnabled( false );
4082 } else {
4083 m_paAddTab->setEnabled( true );
4084 m_paDuplicateTab->setEnabled( true );
4085 KonqFrameTabs* tabContainer = m_pViewManager->tabContainer();
4086 bool state = (tabContainer->count()>1);
4087 m_paRemoveTab->setEnabled( state );
4088 m_paRemoveOtherTabs->setEnabled( state );
4089 m_paBreakOffTab->setEnabled( state );
4090 m_paActivateNextTab->setEnabled( state );
4091 m_paActivatePrevTab->setEnabled( state );
4093 QList<KonqFrameBase*> childFrameList = tabContainer->childFrameList();
4094 Q_ASSERT( !childFrameList.isEmpty() );
4095 m_paMoveTabLeft->setEnabled( currentView() ? currentView()->frame()!=
4096 (QApplication::isRightToLeft() ? childFrameList.last() : childFrameList.first()) : false );
4097 m_paMoveTabRight->setEnabled( currentView() ? currentView()->frame()!=
4098 (QApplication::isRightToLeft() ? childFrameList.first() : childFrameList.last()) : false );
4101 // Can split a view if it's not a toggle view (because a toggle view can be here only once)
4102 bool isNotToggle = m_currentView && !m_currentView->isToggleView();
4103 m_paSplitViewHor->setEnabled( isNotToggle );
4104 m_paSplitViewVer->setEnabled( isNotToggle );
4106 m_paLinkView->setChecked( m_currentView && m_currentView->isLinkedView() );
4108 #if 0
4109 if ( m_currentView && m_currentView->part() &&
4110 ::qobject_cast<KonqDirPart*>( m_currentView->part() ) )
4112 KonqDirPart * dirPart = static_cast<KonqDirPart *>(m_currentView->part());
4113 m_paFindFiles->setEnabled( dirPart->findPart() == 0 );
4115 // Create the copy/move options if not already done
4116 // TODO: move that stuff to dolphin(part)
4117 if ( !m_paCopyFiles )
4119 // F5 is the default key binding for Reload.... a la Windows.
4120 // mc users want F5 for Copy and F6 for move, but I can't make that default.
4123 m_paCopyFiles = actionCollection()->addAction( "copyfiles" );
4124 m_paCopyFiles->setText( i18n("Copy &Files...") );
4125 connect(m_paCopyFiles, SIGNAL(triggered() ), SLOT( slotCopyFiles() ));
4126 m_paCopyFiles->setShortcut(Qt::Key_F7);
4127 m_paMoveFiles = actionCollection()->addAction( "movefiles" );
4128 m_paMoveFiles->setText( i18n("M&ove Files...") );
4129 connect(m_paMoveFiles, SIGNAL(triggered() ), SLOT( slotMoveFiles() ));
4130 m_paMoveFiles->setShortcut(Qt::Key_F8);
4132 QList<QAction*> lst;
4133 lst.append( m_paCopyFiles );
4134 lst.append( m_paMoveFiles );
4135 m_paCopyFiles->setEnabled( false );
4136 m_paMoveFiles->setEnabled( false );
4137 plugActionList( "operations", lst );
4140 else
4142 m_paFindFiles->setEnabled( false );
4144 if (m_paCopyFiles)
4146 unplugActionList( "operations" );
4147 delete m_paCopyFiles;
4148 m_paCopyFiles = 0;
4149 delete m_paMoveFiles;
4150 m_paMoveFiles = 0;
4153 #endif
4156 QString KonqMainWindow::findIndexFile( const QString &dir )
4158 QDir d( dir );
4160 QString f = d.filePath( QLatin1String ( "index.html" ) );
4161 if ( QFile::exists( f ) )
4162 return f;
4164 f = d.filePath( QLatin1String ( "index.htm" ) );
4165 if ( QFile::exists( f ) )
4166 return f;
4168 f = d.filePath( QLatin1String( "index.HTML" ) );
4169 if ( QFile::exists( f ) )
4170 return f;
4172 return QString();
4175 void KonqMainWindow::connectExtension( KParts::BrowserExtension *ext )
4177 KParts::BrowserExtension::ActionSlotMap * actionSlotMap = KParts::BrowserExtension::actionSlotMapPtr();
4178 KParts::BrowserExtension::ActionSlotMap::ConstIterator it = actionSlotMap->constBegin();
4179 KParts::BrowserExtension::ActionSlotMap::ConstIterator itEnd = actionSlotMap->constEnd();
4181 for ( ; it != itEnd ; ++it )
4183 QAction * act = actionCollection()->action( it.key().data() );
4184 //kDebug(1202) << it.key();
4185 if ( act )
4187 // Does the extension have a slot with the name of this action ?
4188 if ( ext->metaObject()->indexOfSlot( it.key()+"()" ) != -1 )
4190 connect( act, SIGNAL( triggered() ), ext, it.value() /* SLOT(slot name) */ );
4191 act->setEnabled( ext->isActionEnabled( it.key() ) );
4192 const QString text = ext->actionText( it.key() );
4193 if ( !text.isEmpty() )
4194 act->setText( text );
4195 // TODO how to re-set the original action text, when switching to a part that didn't call setAction?
4196 // Can't test with Paste...
4197 } else
4198 act->setEnabled(false);
4200 } else kError(1202) << "Error in BrowserExtension::actionSlotMap(), unknown action : " << it.key();
4205 void KonqMainWindow::disconnectExtension( KParts::BrowserExtension *ext )
4207 KParts::BrowserExtension::ActionSlotMap * actionSlotMap = KParts::BrowserExtension::actionSlotMapPtr();
4208 KParts::BrowserExtension::ActionSlotMap::ConstIterator it = actionSlotMap->constBegin();
4209 KParts::BrowserExtension::ActionSlotMap::ConstIterator itEnd = actionSlotMap->constEnd();
4211 for ( ; it != itEnd ; ++it )
4213 QAction * act = actionCollection()->action( it.key().data() );
4214 //kDebug(1202) << it.key();
4215 if ( act && ext->metaObject()->indexOfSlot( it.key()+"()" ) != -1 )
4217 //kDebug(1202) << act << act->name();
4218 act->disconnect( ext );
4223 void KonqMainWindow::enableAction( const char * name, bool enabled )
4225 QAction * act = actionCollection()->action( name );
4226 if (!act)
4227 kWarning(1202) << "Unknown action " << name << " - can't enable" ;
4228 else
4230 if ( m_bLocationBarConnected && (
4231 act==m_paCopy || act==m_paCut || act==m_paPaste ) )
4232 // Don't change action state while the location bar has focus.
4233 return;
4234 //kDebug(1202) << name << enabled;
4235 act->setEnabled( enabled );
4238 // Update "copy files" and "move files" accordingly
4239 if (m_paCopyFiles && !strcmp( name, "copy" ))
4241 m_paCopyFiles->setEnabled( enabled );
4243 else if (m_paMoveFiles && !strcmp( name, "cut" ))
4245 m_paMoveFiles->setEnabled( enabled );
4249 void KonqMainWindow::setActionText(const char * name, const QString& text)
4251 QAction * act = actionCollection()->action(name);
4252 if (!act) {
4253 kWarning(1202) << "Unknown action " << name << "- can't enable" ;
4254 } else {
4255 //kDebug(1202) << name << " text=" << text;
4256 act->setText(text);
4260 void KonqMainWindow::setProfileConfig(const KConfigGroup& cfg)
4262 // Read toolbar settings and window size from profile, and autosave into that profile from now on
4263 setAutoSaveSettings(cfg);
4264 currentProfileChanged();
4267 void KonqMainWindow::currentProfileChanged()
4269 const bool enabled = !m_pViewManager->currentProfile().isEmpty();
4270 m_paSaveViewProfile->setEnabled(enabled);
4271 m_paSaveViewProfile->setText(enabled ? i18n("&Save View Profile \"%1\"...", m_pViewManager->currentProfileText())
4272 : i18n("&Save View Profile..."));
4275 void KonqMainWindow::enableAllActions( bool enable )
4277 //kDebug(1202) << enable;
4278 KParts::BrowserExtension::ActionSlotMap * actionSlotMap = KParts::BrowserExtension::actionSlotMapPtr();
4280 const QList<QAction *> actions = actionCollection()->actions();
4281 QList<QAction *>::ConstIterator it = actions.constBegin();
4282 QList<QAction *>::ConstIterator end = actions.constEnd();
4283 for (; it != end; ++it )
4285 QAction *act = *it;
4286 if ( !act->objectName().startsWith("options_configure") /* do not touch the configureblah actions */
4287 && ( !enable || !actionSlotMap->contains( act->objectName().toLatin1() ) ) ) /* don't enable BE actions */
4288 act->setEnabled( enable );
4290 // This method is called with enable=false on startup, and
4291 // then only once with enable=true when the first view is setup.
4292 // So the code below is where actions that should initially be disabled are disabled.
4293 if (enable)
4295 setUpEnabled( m_currentView ? m_currentView->url() : KUrl() );
4296 // we surely don't have any history buffers at this time
4297 m_paBack->setEnabled( false );
4298 m_paForward->setEnabled( false );
4300 // Load profile submenu
4301 m_pViewManager->profileListDirty( false );
4303 currentProfileChanged();
4305 updateViewActions(); // undo, lock, link and other view-dependent actions
4306 updateClosedItemsAction();
4308 m_paStop->setEnabled( m_currentView && m_currentView->isLoading() );
4310 if (m_toggleViewGUIClient)
4312 QList<QAction*> actions = m_toggleViewGUIClient->actions();
4313 for (int i = 0; i < actions.size(); ++i) {
4314 actions.at(i)->setEnabled( true );
4319 actionCollection()->action( "quit" )->setEnabled( true );
4322 void KonqMainWindow::disableActionsNoView()
4324 // No view -> there are some things we can't do
4325 m_paUp->setEnabled( false );
4326 m_paReload->setEnabled( false );
4327 m_paReloadAllTabs->setEnabled( false );
4328 m_paBack->setEnabled( false );
4329 m_paForward->setEnabled( false );
4330 m_ptaUseHTML->setEnabled( false );
4331 m_paLockView->setEnabled( false );
4332 m_paLockView->setChecked( false );
4333 m_paSplitViewVer->setEnabled( false );
4334 m_paSplitViewHor->setEnabled( false );
4335 m_paRemoveView->setEnabled( false );
4336 m_paLinkView->setEnabled( false );
4337 if (m_toggleViewGUIClient)
4339 QList<QAction*> actions = m_toggleViewGUIClient->actions();
4340 for (int i = 0; i < actions.size(); ++i) {
4341 actions.at(i)->setEnabled( false );
4344 // There are things we can do, though : bookmarks, view profile, location bar, new window,
4345 // settings, etc.
4346 m_paHome->setEnabled( true );
4347 m_pamBookmarks->setEnabled( true );
4348 static const char* const s_enActions[] = { "new_window", "duplicate_window", "open_location",
4349 "toolbar_url_combo", "clear_location", "animated_logo",
4350 "konqintro", "go_most_often", "go_applications",
4351 "go_trash", "go_settings", "go_network_folders", "go_autostart",
4352 "go_url", "go_media", "go_history", "options_configure_extensions", 0 };
4353 for ( int i = 0 ; s_enActions[i] ; ++i )
4355 QAction * act = action(s_enActions[i]);
4356 if (act)
4357 act->setEnabled( true );
4359 m_pamLoadViewProfile->setEnabled( true );
4360 m_paSaveViewProfile->setEnabled( true );
4361 m_paSaveRemoveViewProfile->setEnabled( true );
4362 m_combo->clearTemporary();
4365 void KonqMainWindow::setCaption( const QString &caption )
4367 // KParts sends us empty captions when activating a brand new part
4368 // We can't change it there (in case of apps removing all parts altogether)
4369 // but here we never do that.
4370 if (!caption.isEmpty() && m_currentView) {
4371 //kDebug(1202) << caption;
4373 // Keep an unmodified copy of the caption (before KComponentData::makeStdCaption is applied)
4374 m_currentView->setCaption(caption);
4375 KParts::MainWindow::setCaption(m_currentView->caption());
4379 void KonqMainWindow::showEvent(QShowEvent *event)
4381 // We need to check if our toolbars are shown/hidden here, and set
4382 // our menu items accordingly. We can't do it in the constructor because
4383 // view profiles store toolbar info, and that info is read after
4384 // construct time.
4385 m_paShowMenuBar->setChecked( !menuBar()->isHidden() );
4386 updateBookmarkBar(); // hide if empty
4388 // Call parent method
4389 KParts::MainWindow::showEvent(event);
4392 QString KonqExtendedBookmarkOwner::currentUrl() const
4394 return m_pKonqMainWindow->currentView()->url().url();
4397 QString KonqMainWindow::currentProfile() const
4399 return m_pViewManager->currentProfile();
4402 QString KonqMainWindow::currentURL() const
4404 if ( !m_currentView )
4405 return QString();
4406 QString url = m_currentView->url().prettyUrl();
4408 #if 0 // do we want this?
4409 // Add the name filter (*.txt) at the end of the URL again
4410 if ( m_currentView->part() ) {
4411 const QString nameFilter = m_currentView->nameFilter();
4412 if (!nameFilter.isEmpty()) {
4413 if (!url.endsWith('/'))
4414 url += '/';
4415 url += nameFilter;
4418 #endif
4419 return url;
4422 bool KonqExtendedBookmarkOwner::supportsTabs() const
4424 return true;
4427 QList<QPair<QString, QString> > KonqExtendedBookmarkOwner::currentBookmarkList() const
4429 QList<QPair<QString, QString> > list;
4430 KonqFrameTabs* tabContainer = m_pKonqMainWindow->viewManager()->tabContainer();
4432 foreach ( KonqFrameBase* frame, tabContainer->childFrameList() )
4434 if ( !frame || !frame->activeChildView() )
4435 continue;
4436 if( frame->activeChildView()->locationBarURL().isEmpty() )
4437 continue;
4438 list << qMakePair( frame->activeChildView()->caption(),
4439 frame->activeChildView()->url().url() );
4441 return list;
4444 QString KonqExtendedBookmarkOwner::currentTitle() const
4446 return m_pKonqMainWindow->currentTitle();
4449 void KonqExtendedBookmarkOwner::openInNewTab(const KBookmark &bm)
4451 bool newTabsInFront = KonqSettings::newTabsInFront();
4452 if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
4453 newTabsInFront = !newTabsInFront;
4455 KonqOpenURLRequest req;
4456 req.browserArgs.setNewTab(true);
4457 req.newTabInFront = newTabsInFront;
4458 req.openAfterCurrentPage = false;
4459 req.forceAutoEmbed = true;
4461 m_pKonqMainWindow->openUrl( 0, bm.url(), QString(), req );
4464 void KonqExtendedBookmarkOwner::openFolderinTabs(const KBookmarkGroup &grp)
4466 bool newTabsInFront = KonqSettings::newTabsInFront();
4467 if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
4468 newTabsInFront = !newTabsInFront;
4469 KonqOpenURLRequest req;
4470 req.browserArgs.setNewTab(true);
4471 req.newTabInFront = false;
4472 req.openAfterCurrentPage = false;
4473 req.forceAutoEmbed = true;
4475 const QList<KUrl> list = grp.groupUrlList();
4476 if (list.isEmpty())
4477 return;
4479 if (list.size() > 20) {
4480 if(KMessageBox::questionYesNo(m_pKonqMainWindow,
4481 i18n("You have requested to open more than 20 bookmarks in tabs. "
4482 "This might take a while. Continue?"),
4483 i18n("Open bookmarks folder in new tabs")) != KMessageBox::Yes)
4484 return;
4487 QList<KUrl>::ConstIterator it = list.constBegin();
4488 QList<KUrl>::ConstIterator end = list.constEnd();
4489 --end;
4490 for (; it != end; ++it )
4492 m_pKonqMainWindow->openUrl( 0, *it, QString(), req );
4494 if ( newTabsInFront )
4496 req.newTabInFront = true;
4498 m_pKonqMainWindow->openUrl( 0, *end, QString(), req );
4501 void KonqExtendedBookmarkOwner::openInNewWindow(const KBookmark &bm)
4503 KonqMisc::createNewWindow( bm.url(), KParts::OpenUrlArguments() );
4506 QString KonqMainWindow::currentTitle() const
4508 return m_currentView ? m_currentView->caption() : QString();
4511 void KonqMainWindow::slotPopupMenu( const QPoint &global, const KUrl &url, mode_t mode, const KParts::OpenUrlArguments &args, const KParts::BrowserArguments& browserArgs, KParts::BrowserExtension::PopupFlags flags, const KParts::BrowserExtension::ActionGroupMap& actionGroups )
4513 KFileItem item( url, args.mimeType(), mode );
4514 KFileItemList items;
4515 items.append( item );
4516 slotPopupMenu( global, items, args, browserArgs, flags, actionGroups );
4519 void KonqMainWindow::slotPopupMenu( const QPoint &global, const KFileItemList &items, const KParts::OpenUrlArguments &args, const KParts::BrowserArguments& browserArgs, KParts::BrowserExtension::PopupFlags itemFlags, const KParts::BrowserExtension::ActionGroupMap& _actionGroups )
4521 KParts::BrowserExtension::ActionGroupMap actionGroups = _actionGroups;
4523 KonqView * m_oldView = m_currentView;
4524 KonqView * currentView = childView( static_cast<KParts::ReadOnlyPart *>( sender()->parent() ) );
4526 //kDebug() << "m_oldView=" << m_oldView << "new currentView=" << currentView << "passive:" << currentView->isPassiveMode();
4528 if ( (m_oldView != currentView) && currentView->isPassiveMode() )
4530 // Make this view active only temporarily (because it's passive)
4531 m_currentView = currentView;
4533 if ( m_oldView && m_oldView->browserExtension() )
4534 disconnectExtension( m_oldView->browserExtension() );
4535 if ( m_currentView->browserExtension() )
4536 connectExtension( m_currentView->browserExtension() );
4538 // Note that if m_oldView!=currentView and currentView isn't passive,
4539 // then the KParts mechanism has already noticed the click in it,
4540 // but KonqViewManager delays the GUI-rebuilding with a single-shot timer.
4541 // Right after the popup shows up, currentView _will_ be m_currentView.
4543 //kDebug(1202) << "current view=" << m_currentView << m_currentView->part()->metaObject()->className();
4545 // This action collection is used to pass actions to KonqPopupMenu.
4546 // It has to be a KActionCollection instead of a KActionPtrList because we need
4547 // the actionStatusText signal...
4548 KActionCollection popupMenuCollection( (QWidget*)0 );
4550 // m_paBack is a submenu, for the toolbar & edit menu "back",
4551 // but in the RMB we want a simple one-click back instead.
4552 KAction* simpleBack = KStandardAction::back( this, SLOT(slotBack()), &popupMenuCollection );
4553 simpleBack->setEnabled( m_paBack->isEnabled() );
4554 popupMenuCollection.addAction( "go_back", simpleBack );
4556 KAction* simpleForward = KStandardAction::forward( this, SLOT(slotForward()), &popupMenuCollection );
4557 simpleForward->setEnabled( m_paForward->isEnabled() );
4558 popupMenuCollection.addAction( "go_forward", simpleForward );
4560 popupMenuCollection.addAction( "go_up", m_paUp );
4561 popupMenuCollection.addAction( "reload", m_paReload );
4562 popupMenuCollection.addAction( "closeditems", m_paClosedItems );
4564 #if 0
4565 popupMenuCollection.addAction( "find", m_paFindFiles );
4566 #endif
4568 popupMenuCollection.addAction( "undo", m_paUndo );
4569 popupMenuCollection.addAction( "cut", m_paCut );
4570 popupMenuCollection.addAction( "copy", m_paCopy );
4571 popupMenuCollection.addAction( "paste", m_paPaste );
4573 // The pasteto action is used when clicking on a dir, to paste into it.
4574 KAction *actPaste = KStandardAction::paste( this, SLOT( slotPopupPasteTo() ), this );
4575 actPaste->setEnabled( m_paPaste->isEnabled() );
4576 popupMenuCollection.addAction( "pasteto", actPaste );
4578 prepareForPopupMenu(items, args, browserArgs);
4580 bool sReading = false;
4581 if (!m_popupUrl.isEmpty()) {
4582 sReading = KProtocolManager::supportsReading(m_popupUrl);
4585 // Don't set the view URL for a toggle view.
4586 // (This is a bit of a hack for the directory tree....)
4587 // ## should use the new currentView->isHierarchicalView() instead?
4588 // Would this be correct for the konqlistview tree view?
4589 KUrl viewURL = currentView->isToggleView() ? KUrl() : currentView->url();
4591 bool openedForViewURL = false;
4592 //bool dirsSelected = false;
4593 bool devicesFile = false;
4595 if ( items.count() == 1 )
4597 const KUrl firstURL = items.first().url();
4598 if ( !viewURL.isEmpty() )
4600 //firstURL.cleanPath();
4601 openedForViewURL = firstURL.equals( viewURL, KUrl::CompareWithoutTrailingSlash );
4603 devicesFile = firstURL.protocol().indexOf("device", 0, Qt::CaseInsensitive) == 0;
4604 //dirsSelected = S_ISDIR( items.first()->mode() );
4606 //kDebug(1202) << "viewURL=" << viewURL;
4608 KUrl url = viewURL;
4609 url.cleanPath();
4610 bool isIntoTrash = url.protocol() == "trash" || url.url().startsWith( "system:/trash" );
4611 const bool doTabHandling = !openedForViewURL && !isIntoTrash && sReading;
4612 const bool showEmbeddingServices = items.count() == 1 && !m_popupMimeType.isEmpty() &&
4613 !isIntoTrash && !devicesFile &&
4614 (itemFlags & KParts::BrowserExtension::ShowTextSelectionItems) == 0;
4616 KService::List embeddingServices;
4617 if ( showEmbeddingServices ) {
4618 const QString currentServiceName = currentView->service()->desktopEntryName();
4620 // List of services for the "Preview In" submenu.
4621 embeddingServices = KMimeTypeTrader::self()->query(
4622 m_popupMimeType,
4623 "KParts/ReadOnlyPart",
4624 // Obey "HideFromMenus". It defaults to false so we want "absent or true"
4625 // (wow, testing for 'true' if absent doesn't work, so order matters)
4626 "(not exist [X-KDE-BrowserView-HideFromMenus] or not [X-KDE-BrowserView-HideFromMenus]) "
4627 "and DesktopEntryName != '"+currentServiceName+"' "
4628 // I had an old local dirtree.desktop without lib, no need for invalid entries
4629 "and exist [Library]");
4632 PopupMenuGUIClient *konqyMenuClient = new PopupMenuGUIClient( embeddingServices,
4633 actionGroups,
4634 !menuBar()->isVisible() ? m_paShowMenuBar : 0,
4635 fullScreenMode() ? m_ptaFullScreen : 0
4637 qRegisterMetaType<KService::Ptr>("KService::Ptr");
4638 connect(konqyMenuClient, SIGNAL(openEmbedded(KService::Ptr)),
4639 this, SLOT(slotOpenEmbedded(KService::Ptr)), Qt::QueuedConnection);
4642 // Those actions go into the PopupMenuGUIClient, since that's the one defining them.
4643 QList<QAction *> tabHandlingActions;
4644 if( doTabHandling )
4646 if (browserArgs.forcesNewWindow()) {
4647 QAction* act = konqyMenuClient->actionCollection()->addAction( "sameview" );
4648 act->setText( i18n( "Open in T&his Window" ) );
4649 act->setToolTip( i18n( "Open the document in current window" ) );
4650 connect(act, SIGNAL(triggered() ), SLOT( slotPopupThisWindow() ));
4651 tabHandlingActions.append(act);
4653 QAction* actNewWindow = konqyMenuClient->actionCollection()->addAction( "newview" );
4654 actNewWindow->setIcon( KIcon("window-new") );
4655 actNewWindow->setText( i18n( "Open in New &Window" ) );
4656 actNewWindow->setToolTip( i18n( "Open the document in a new window" ) );
4657 connect(actNewWindow, SIGNAL(triggered()), SLOT( slotPopupNewWindow() ));
4658 tabHandlingActions.append(actNewWindow);
4660 QAction* actNewTab = konqyMenuClient->actionCollection()->addAction( "openintab" );
4661 actNewTab->setIcon( KIcon("tab-new") );
4662 actNewTab->setText( i18n( "Open in &New Tab" ) );
4663 connect(actNewTab, SIGNAL(triggered()), SLOT( slotPopupNewTab() ));
4664 actNewTab->setToolTip( i18n( "Open the document in a new tab" ) );
4665 tabHandlingActions.append(actNewTab);
4667 QAction* separator = new QAction(konqyMenuClient->actionCollection());
4668 separator->setSeparator(true);
4669 tabHandlingActions.append(separator);
4672 if (currentView->isHierarchicalView())
4673 itemFlags |= KParts::BrowserExtension::ShowCreateDirectory;
4675 KonqPopupMenu::Flags kpf = 0;
4677 if (doTabHandling)
4678 actionGroups.insert("tabhandling", tabHandlingActions);
4679 //if (kpf & KonqPopupMenu::IsLink)
4680 // actionGroups.insert("linkactions", linkActions);
4681 // TODO actionGroups.insert("partactions", partActions);
4683 QPointer<KonqPopupMenu> pPopupMenu = new KonqPopupMenu(
4684 items,
4685 viewURL,
4686 popupMenuCollection,
4687 m_pMenuNew,
4688 kpf,
4689 itemFlags,
4690 // This parent ensures that if the part destroys itself (e.g. KHTML redirection),
4691 // it will close the popupmenu
4692 currentView->part()->widget(),
4693 s_bookmarkManager,
4694 actionGroups );
4696 if ( openedForViewURL && !viewURL.isLocalFile() )
4697 pPopupMenu->setURLTitle( currentView->caption() );
4699 QPointer<KParts::BrowserExtension> be = ::qobject_cast<KParts::BrowserExtension *>(sender());
4701 if (be) {
4702 QObject::connect( this, SIGNAL(popupItemsDisturbed()), pPopupMenu, SLOT(close()) );
4703 QObject::connect( be, SIGNAL(itemsRemoved(const KFileItemList &)),
4704 this, SLOT(slotItemsRemoved(const KFileItemList &)) );
4708 QPointer<QObject> guard( this ); // #149736, window could be deleted inside popupmenu event loop
4709 pPopupMenu->exec( global );
4711 delete pPopupMenu;
4713 // We're sort of misusing KActionCollection here, but we need it for the actionStatusText signal...
4714 // Anyway. If the action belonged to the view, and the view got deleted, we don't want ~KActionCollection
4715 // to iterate over those deleted actions
4716 /*KActionPtrList lst = popupMenuCollection.actions();
4717 KActionPtrList::iterator it = lst.begin();
4718 for ( ; it != lst.end() ; ++it )
4719 popupMenuCollection.take( *it );*/
4721 if ( guard.isNull() ) // the placement of this test is very important, double-check #149736 if moving stuff around
4722 return;
4724 if (be) {
4725 QObject::disconnect( be, SIGNAL(itemsRemoved(const KFileItemList &)),
4726 this, SLOT(slotItemsRemoved(const KFileItemList &)) );
4729 delete konqyMenuClient;
4730 m_popupItems.clear();
4732 // Deleted by konqyMenuClient's actioncollection
4733 //delete actNewTab;
4734 //delete actNewWindow;
4736 delete actPaste;
4738 // Restore current view if current is passive
4739 if ( (m_oldView != currentView) && (currentView == m_currentView) && currentView->isPassiveMode() )
4741 //kDebug() << "restoring active view" << m_oldView;
4742 if ( m_currentView->browserExtension() )
4743 disconnectExtension( m_currentView->browserExtension() );
4744 if ( m_oldView )
4746 if ( m_oldView->browserExtension() )
4748 connectExtension( m_oldView->browserExtension() );
4749 m_currentView = m_oldView;
4751 // Special case: RMB + renaming in sidebar; setFocus would abort editing.
4752 QWidget* fw = focusWidget();
4753 if ( !fw || !::qobject_cast<QLineEdit*>( fw ) )
4754 m_oldView->part()->widget()->setFocus();
4759 void KonqMainWindow::prepareForPopupMenu(const KFileItemList &items, const KParts::OpenUrlArguments &args, const KParts::BrowserArguments& browserArgs)
4761 if (!items.isEmpty()) {
4762 m_popupUrl = items.first().url();
4763 m_popupMimeType = items.first().mimetype();
4765 else
4767 m_popupUrl = KUrl();
4768 m_popupMimeType.clear();
4770 // We will need these if we call the newTab slot
4771 m_popupItems = items;
4772 m_popupUrlArgs = args;
4773 m_popupUrlArgs.setMimeType( QString() ); // Reset so that Open in New Window/Tab does mimetype detection
4774 m_popupUrlBrowserArgs = browserArgs;
4777 void KonqMainWindow::slotItemsRemoved(const KFileItemList &items)
4779 QListIterator<KFileItem> it(items);
4780 while (it.hasNext()) {
4781 if (m_popupItems.contains(it.next())) {
4782 emit popupItemsDisturbed();
4783 return;
4788 Q_DECLARE_METATYPE(KService::Ptr)
4789 void KonqMainWindow::slotOpenEmbedded(KService::Ptr service)
4791 m_currentView->stop();
4792 m_currentView->setLocationBarURL(m_popupUrl);
4793 m_currentView->setTypedURL(QString());
4794 if ( m_currentView->changePart( m_popupMimeType,
4795 service->desktopEntryName(), true ) )
4796 m_currentView->openUrl( m_popupUrl, m_popupUrl.pathOrUrl() );
4799 void KonqMainWindow::slotDatabaseChanged()
4801 if ( KSycoca::isChanged("mimetypes") )
4803 MapViews::ConstIterator it = m_mapViews.constBegin();
4804 MapViews::ConstIterator end = m_mapViews.constEnd();
4805 for (; it != end; ++it )
4806 (*it)->callExtensionMethod( "refreshMimeTypes" );
4810 void KonqMainWindow::slotPopupPasteTo()
4812 if ( !m_currentView || m_popupUrl.isEmpty() )
4813 return;
4814 m_currentView->callExtensionURLMethod( "pasteTo", m_popupUrl );
4817 void KonqMainWindow::slotReconfigure()
4819 reparseConfiguration();
4822 void KonqMainWindow::reparseConfiguration()
4824 kDebug(1202);
4826 KonqSettings::self()->readConfig();
4827 m_pViewManager->applyConfiguration();
4829 m_bHTMLAllowed = KonqSettings::htmlAllowed();
4831 if (m_combo)
4832 m_combo->setFont( KGlobalSettings::generalFont() );
4834 MapViews::ConstIterator it = m_mapViews.constBegin();
4835 MapViews::ConstIterator end = m_mapViews.constEnd();
4836 for (; it != end; ++it )
4837 (*it)->reparseConfiguration();
4840 void KonqMainWindow::saveProperties( KConfigGroup& config )
4842 // Ensure no crash if the sessionmanager timer fires before the ctor is done
4843 // This can happen via ToggleViewGUIClient -> KServiceTypeTrader::query
4844 // -> KSycoca running kbuildsycoca -> nested event loop.
4845 if (m_fullyConstructed) {
4846 KonqFrameBase::Options flags = KonqFrameBase::saveHistoryItems;
4847 m_pViewManager->saveViewProfileToGroup(config, flags);
4851 void KonqMainWindow::readProperties( const KConfigGroup& configGroup )
4853 // ######### THIS CANNOT WORK. It's too late to change the xmlfile, the GUI has been built already!
4854 // We need to delay doing setXMLFile+createGUI until we know which profile we are going to use, then...
4855 // TODO: Big refactoring needed for this feature. On the other hand, all default profiles shipped with
4856 // konqueror use konqueror.rc again, so the need for this is almost zero now.
4857 const QString xmluiFile = configGroup.readEntry("XMLUIFile","konqueror.rc");
4858 setXMLFile( KonqViewManager::normalizedXMLFileName(xmluiFile) );
4860 m_pViewManager->loadViewProfileFromGroup( configGroup, QString() /*no profile name*/ );
4861 // read window settings
4862 applyMainWindowSettings( configGroup, true );
4865 void KonqMainWindow::setInitialFrameName( const QString &name )
4867 m_initialFrameName = name;
4870 void KonqMainWindow::updateOpenWithActions()
4872 unplugActionList( "openwithbase" );
4873 unplugActionList( "openwith" );
4875 qDeleteAll(m_openWithActions);
4876 m_openWithActions.clear();
4878 delete m_openWithMenu;
4879 m_openWithMenu = 0;
4881 if (!KAuthorized::authorizeKAction("openwith"))
4882 return;
4884 m_openWithMenu = new KActionMenu( i18n("&Open With"), this );
4886 const KService::List & services = m_currentView->appServiceOffers();
4887 KService::List::ConstIterator it = services.constBegin();
4888 const KService::List::ConstIterator end = services.constEnd();
4890 const int baseOpenWithItems = qMax(KonqSettings::openWithItems(), 0);
4892 int idxService = 0;
4893 for (; it != end; ++it, ++idxService)
4895 QAction *action;
4897 if (idxService < baseOpenWithItems)
4898 action = new QAction(i18n("Open with %1", (*it)->name()), this);
4899 else
4900 action = new QAction((*it)->name(), this);
4901 action->setIcon( KIcon( (*it)->icon() ) );
4903 connect( action, SIGNAL( triggered() ),
4904 this, SLOT( slotOpenWith() ) );
4906 actionCollection()->addAction((*it)->desktopEntryName(), action);
4907 if (idxService < baseOpenWithItems)
4908 m_openWithActions.append(action);
4909 else
4910 m_openWithMenu->addAction(action);
4913 if ( services.count() > 0 )
4915 plugActionList("openwithbase", m_openWithActions);
4916 QList<QAction*> openWithActionsMenu;
4917 if (idxService > baseOpenWithItems)
4919 openWithActionsMenu.append(m_openWithMenu);
4921 QAction *sep = new QAction( this );
4922 sep->setSeparator( true );
4923 openWithActionsMenu.append(sep);
4924 plugActionList("openwith", openWithActionsMenu);
4928 void KonqMainWindow::updateViewModeActions()
4930 unplugViewModeActions();
4931 Q_FOREACH( QAction* action, m_viewModesGroup->actions() ) {
4932 Q_FOREACH( QWidget *w, action->associatedWidgets() )
4933 w->removeAction( action );
4934 delete action;
4937 delete m_viewModeMenu;
4938 m_viewModeMenu = 0;
4940 const KService::List services = m_currentView->partServiceOffers();
4941 if ( services.count() <= 1 )
4942 return;
4944 m_viewModeMenu = new KActionMenu( i18nc("@action:inmenu View", "&View Mode"), this );
4945 //actionCollection()->addAction( "viewModeMenu", m_viewModeMenu );
4947 KService::List::ConstIterator it = services.constBegin();
4948 const KService::List::ConstIterator end = services.constEnd();
4949 for (; it != end; ++it) {
4950 const KService::Ptr service = *it;
4951 const QVariant prop = service->property( "X-KDE-BrowserView-Toggable" );
4952 if (prop.isValid() && prop.toBool()) // No toggable views in view mode
4953 continue;
4955 const QString desktopEntryName = service->desktopEntryName();
4956 bool bIsCurrentView = desktopEntryName == m_currentView->service()->desktopEntryName();
4958 const QList<KServiceAction> actions = service->actions();
4959 if (!actions.isEmpty()) {
4961 // The service provides several view modes, like DolphinPart
4962 // -> create one action per view mode
4963 Q_FOREACH(const KServiceAction& serviceAction, actions) {
4964 // Create a KToggleAction for each view mode, and plug it into the menu
4965 KToggleAction* action = new KToggleAction(KIcon(serviceAction.icon()), serviceAction.text(), this);
4966 //actionCollection()->addAction(desktopEntryName /*not unique!*/, action);
4967 action->setObjectName(desktopEntryName);
4968 action->setData(QVariant(serviceAction.name()));
4969 action->setActionGroup(m_viewModesGroup);
4970 m_viewModeMenu->menu()->addAction(action);
4971 if (bIsCurrentView && m_currentView->internalViewMode() == serviceAction.name()) {
4972 action->setChecked(true);
4976 } else {
4977 // The service only provides one view mode (common case)
4979 QString serviceText = service->genericName();
4980 if (serviceText.isEmpty())
4981 serviceText = service->name();
4983 // Create a KToggleAction for this view mode, and plug it into the menu
4984 KToggleAction* action = new KToggleAction(KIcon(service->icon()), serviceText, this);
4985 actionCollection()->addAction(desktopEntryName, action);
4986 action->setObjectName(desktopEntryName);
4987 action->setActionGroup(m_viewModesGroup);
4988 m_viewModeMenu->menu()->addAction(action);
4990 action->setChecked(bIsCurrentView);
4994 // No view mode for actions toggable views
4995 // (The other way would be to enforce a better servicetype for them, than Browser/View)
4996 if (!m_currentView->isToggleView()
4997 /* already tested: && services.count() > 1 */
4998 && m_viewModeMenu) {
4999 plugViewModeActions();
5003 void KonqMainWindow::slotInternalViewModeChanged()
5005 KParts::ReadOnlyPart *part = static_cast<KParts::ReadOnlyPart *>(sender());
5006 KonqView * view = m_mapViews.value(part);
5007 if (view) {
5008 const QString actionName = view->service()->desktopEntryName();
5009 const QString actionData = view->internalViewMode();
5010 Q_FOREACH(QAction* action, m_viewModesGroup->actions()) {
5011 if (action->objectName() == actionName &&
5012 action->data().toString() == actionData) {
5013 action->setChecked(true);
5014 break;
5020 void KonqMainWindow::plugViewModeActions()
5022 QList<QAction*> lst;
5023 lst.append( m_viewModeMenu );
5024 plugActionList( "viewmode", lst );
5027 void KonqMainWindow::unplugViewModeActions()
5029 unplugActionList( "viewmode" );
5032 void KonqMainWindow::updateBookmarkBar()
5034 KToolBar * bar = qFindChild<KToolBar *>(this, "bookmarkToolBar");
5035 if (!bar) return;
5036 if (m_paBookmarkBar && bar->actions().isEmpty() )
5037 bar->hide();
5041 void KonqMainWindow::closeEvent( QCloseEvent *e )
5043 // This breaks session management (the window is withdrawn in kwin)
5044 // so let's do this only when closed by the user.
5045 KonquerorApplication* konqApp = qobject_cast<KonquerorApplication *>(qApp);
5047 // konqApp is 0 in unit tests
5048 if (konqApp && konqApp->closedByUser()) {
5049 KonqFrameTabs* tabContainer = m_pViewManager->tabContainer();
5050 if ( tabContainer->count() > 1 )
5052 KSharedConfig::Ptr config = KGlobal::config();
5053 KConfigGroup cs( config, QLatin1String("Notification Messages") );
5055 if ( !cs.hasKey( "MultipleTabConfirm" ) )
5057 switch (
5058 KMessageBox::warningYesNoCancel(
5059 this,
5060 i18n("You have multiple tabs open in this window, "
5061 "are you sure you want to quit?"),
5062 i18n("Confirmation"),
5063 KStandardGuiItem::quit(),
5064 KGuiItem(i18n( "C&lose Current Tab" ), "tab-close"),
5065 KStandardGuiItem::cancel(),
5066 "MultipleTabConfirm"
5069 case KMessageBox::Yes :
5070 break;
5071 case KMessageBox::No :
5073 e->ignore();
5074 slotRemoveTab();
5075 return;
5077 break;
5078 case KMessageBox::Cancel :
5080 e->ignore();
5081 return;
5087 KonqView *originalView = m_currentView;
5088 MapViews::ConstIterator it = m_mapViews.constBegin();
5089 MapViews::ConstIterator end = m_mapViews.constEnd();
5090 for (; it != end; ++it ) {
5091 KonqView *view = it.value();
5092 if (view && view->part() && (view->part()->metaObject()->indexOfProperty("modified") != -1) ) {
5093 QVariant prop = view->part()->property("modified");
5094 if (prop.isValid() && prop.toBool()) {
5095 m_pViewManager->showTab( view );
5096 const QString question = m_pViewManager->isTabBarVisible()
5097 ? i18n("This tab contains changes that have not been submitted.\nClosing the window will discard these changes.")
5098 : i18n("This page contains changes that have not been submitted.\nClosing the window will discard these changes.");
5099 if ( KMessageBox::warningContinueCancel( this, question,
5100 i18n("Discard Changes?"), KGuiItem(i18n("&Discard Changes"),"application-exit"), KStandardGuiItem::cancel(), "discardchangesclose") != KMessageBox::Continue )
5102 e->ignore();
5103 m_pViewManager->showTab( originalView );
5104 return;
5110 if (settingsDirty() && autoSaveSettings())
5111 saveAutoSaveSettings();
5113 addClosedWindowToUndoList();
5115 hide();
5116 qApp->flush();
5118 // We're going to close - tell the parts
5119 MapViews::ConstIterator it = m_mapViews.constBegin();
5120 MapViews::ConstIterator end = m_mapViews.constEnd();
5121 for (; it != end; ++it )
5123 if ( (*it)->part() && (*it)->part()->widget() )
5124 QApplication::sendEvent( (*it)->part()->widget(), e );
5126 KParts::MainWindow::closeEvent( e );
5127 if( isPreloaded() && !kapp->sessionSaving())
5128 { // queryExit() refused closing, hide instead
5129 hide();
5133 void KonqMainWindow::addClosedWindowToUndoList()
5135 kDebug(1202);
5137 // 1. We get the current title
5138 int numTabs = m_pViewManager->tabContainer()->childFrameList().count();
5139 QString title( i18n("no name") );
5141 if(m_currentView)
5142 title = m_currentView->caption();
5144 // 2. Create the KonqClosedWindowItem and save its config
5145 KonqClosedWindowItem* closedWindowItem = new KonqClosedWindowItem(title, m_pUndoManager->newCommandSerialNumber(), numTabs);
5146 saveProperties( closedWindowItem->configGroup() );
5148 // 3. Add the KonqClosedWindowItem to the undo list
5149 m_paClosedItems->setEnabled(true);
5150 m_pUndoManager->addClosedWindowItem( closedWindowItem );
5152 kDebug(1202) << "done";
5155 bool KonqMainWindow::queryExit()
5157 if( kapp && kapp->sessionSaving()) // *sigh*
5158 return true;
5159 return !stayPreloaded();
5162 void KonqMainWindow::updateWindowIcon()
5164 const QString url = m_combo->currentText();
5165 // TODO (kfm-devel email 13/09/2008) should we use a profile-defined icon instead of a url-dependent window icon?
5166 const QPixmap pix = KonqPixmapProvider::self()->pixmapFor( url );
5167 KParts::MainWindow::setWindowIcon( pix );
5169 QPixmap big = pix;
5170 if (!url.isEmpty()) {
5171 big = KonqPixmapProvider::self()->pixmapFor( url, KIconLoader::SizeMedium );
5174 KWindowSystem::setIcons( winId(), big, pix );
5177 void KonqMainWindow::slotIntro()
5179 openUrl( 0, KUrl("about:") );
5182 void KonqMainWindow::goURL()
5184 QLineEdit *lineEdit = m_combo->lineEdit();
5185 if ( !lineEdit )
5186 return;
5188 QKeyEvent event( QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, QChar('\n') );
5189 QApplication::sendEvent( lineEdit, &event );
5193 * Adds the URL of a KonqView to the closed tabs list.
5194 * This slot gets called each time a View is closed.
5196 void KonqMainWindow::slotAddClosedUrl(KonqFrameBase *tab)
5198 kDebug(1202);
5199 QString title( i18n("no name") ), url("about:blank");
5201 // Did the tab contain a single frame, or a splitter?
5202 KonqFrame* frame = dynamic_cast<KonqFrame *>(tab);
5203 if (!frame) {
5204 KonqFrameContainer* frameContainer = dynamic_cast<KonqFrameContainer *>(tab);
5205 if (frameContainer->activeChildView())
5206 frame = frameContainer->activeChildView()->frame();
5209 KParts::ReadOnlyPart* part = frame ? frame->part() : 0;
5210 if (part)
5211 url = part->url().url();
5212 if (frame)
5213 title = frame->title().trimmed();
5214 if (title.isEmpty())
5215 title = url;
5216 title = KStringHandler::csqueeze( title, 50 );
5218 // Now we get the position of the tab
5219 const int index = m_pViewManager->tabContainer()->childFrameList().indexOf(tab);
5221 KonqClosedTabItem* closedTabItem = new KonqClosedTabItem(url, title, index, m_pUndoManager->newCommandSerialNumber());
5223 QString prefix = KonqFrameBase::frameTypeToString( tab->frameType() ) + QString::number(0);
5224 closedTabItem->configGroup().writeEntry( "RootItem", prefix );
5225 prefix.append( QLatin1Char( '_' ) );
5226 KonqFrameBase::Options flags = KonqFrameBase::saveHistoryItems;
5227 tab->saveConfig( closedTabItem->configGroup(), prefix, flags, 0L, 0, 1);
5229 m_paClosedItems->setEnabled(true);
5230 m_pUndoManager->addClosedTabItem( closedTabItem );
5232 kDebug(1202) << "done";
5235 void KonqMainWindow::slotLocationLabelActivated()
5237 focusLocationBar();
5238 m_combo->lineEdit()->selectAll();
5241 void KonqMainWindow::slotOpenURL( const KUrl& url )
5243 openUrl( 0, url );
5246 bool KonqMainWindow::sidebarVisible() const
5248 QAction *a = m_toggleViewGUIClient->action("konq_sidebartng");
5249 return (a && static_cast<KToggleAction*>(a)->isChecked());
5252 bool KonqMainWindow::fullScreenMode() const
5254 return m_ptaFullScreen->isChecked();
5257 void KonqMainWindow::slotAddWebSideBar(const KUrl& url, const QString& name)
5259 if (url.url().isEmpty() && name.isEmpty())
5260 return;
5262 kDebug(1202) << "Requested to add URL" << url << " [" << name << "] to the sidebar!";
5264 QAction *a = m_toggleViewGUIClient->action("konq_sidebartng");
5265 if (!a) {
5266 KMessageBox::sorry(0, i18n("Your sidebar is not functional or unavailable. A new entry cannot be added."), i18n("Web Sidebar"));
5267 return;
5270 int rc = KMessageBox::questionYesNo(0,
5271 i18n("Add new web extension \"%1\" to your sidebar?",
5272 name.isEmpty() ? name : url.prettyUrl()),
5273 i18n("Web Sidebar"),KGuiItem(i18n("Add")),KGuiItem(i18n("Do Not Add")));
5275 if (rc == KMessageBox::Yes) {
5276 // Show the sidebar
5277 if (!static_cast<KToggleAction*>(a)->isChecked()) {
5278 a->trigger();
5281 // Tell it to add a new panel
5282 MapViews::ConstIterator it;
5283 for (it = viewMap().constBegin(); it != viewMap().constEnd(); ++it) {
5284 KonqView *view = it.value();
5285 if (view) {
5286 KService::Ptr svc = view->service();
5287 if (svc->desktopEntryName() == "konq_sidebartng") {
5288 emit view->browserExtension()->addWebSideBar(url, name);
5289 break;
5296 void KonqMainWindow::bookmarksIntoCompletion( const KBookmarkGroup& group )
5298 static const QString& http = KGlobal::staticQString( "http" );
5299 static const QString& ftp = KGlobal::staticQString( "ftp" );
5301 if ( group.isNull() )
5302 return;
5304 for ( KBookmark bm = group.first();
5305 !bm.isNull(); bm = group.next(bm) ) {
5306 if ( bm.isGroup() ) {
5307 bookmarksIntoCompletion( bm.toGroup() );
5308 continue;
5311 KUrl url = bm.url();
5312 if ( !url.isValid() )
5313 continue;
5315 QString u = url.prettyUrl();
5316 s_pCompletion->addItem( u );
5318 if ( url.isLocalFile() )
5319 s_pCompletion->addItem( url.path() );
5320 else if ( url.protocol() == http )
5321 s_pCompletion->addItem( u.mid( 7 ));
5322 else if ( url.protocol() == ftp &&
5323 url.host().startsWith( ftp ) )
5324 s_pCompletion->addItem( u.mid( 6 ) );
5329 // the smart popup completion code , <l.lunak@kde.org>
5332 // prepend http://www. or http:// if there's no protocol in 's'
5333 // used only when there are no completion matches
5334 static QString hp_tryPrepend( const QString& s )
5336 if( s.isEmpty() || s[ 0 ] == '/' )
5337 return QString();
5338 for( int pos = 0;
5339 pos < s.length() - 2; // 4 = ://x
5340 ++pos )
5342 if( s[ pos ] == ':' && s[ pos + 1 ] == '/' && s[ pos + 2 ] == '/' )
5343 return QString();
5344 if( !s[ pos ].isLetter() )
5345 break;
5347 return ( s.startsWith( "www." ) ? "http://" : "http://www." ) + s;
5351 static void hp_removeDupe( KCompletionMatches& l, const QString& dupe,
5352 KCompletionMatches::Iterator it_orig )
5354 KCompletionMatches::Iterator it = it_orig + 1;
5355 while (it != l.end()) {
5356 if( (*it).value() == dupe ) {
5357 (*it_orig).first = qMax( (*it_orig).first, (*it).key());
5358 it = l.erase( it );
5359 continue;
5361 ++it;
5365 // remove duplicates like 'http://www.kde.org' and 'http://www.kde.org/'
5366 // (i.e. the trailing slash)
5367 // some duplicates are also created by prepending protocols
5368 static void hp_removeDuplicates( KCompletionMatches& l )
5370 QString http = "http://";
5371 QString ftp = "ftp://ftp.";
5372 QString file = "file:";
5373 QString file2 = "file://";
5374 l.removeDuplicates();
5375 for( KCompletionMatches::Iterator it = l.begin();
5376 it != l.end();
5377 ++it ) {
5378 QString str = (*it).value();
5379 if( str.startsWith( http )) {
5380 if( str.indexOf( '/', 7 ) < 0 ) { // http://something<noslash>
5381 hp_removeDupe( l, str + '/', it );
5382 hp_removeDupe( l, str.mid( 7 ) + '/', it );
5383 } else if( str[ str.length() - 1 ] == '/' ) {
5384 hp_removeDupe( l, str.left( str.length() - 1 ), it );
5385 hp_removeDupe( l, str.left( str.length() - 1 ).mid( 7 ), it );
5387 hp_removeDupe( l, str.mid( 7 ), it );
5389 else if( str.startsWith( ftp )) // ftp://ftp.
5390 hp_removeDupe( l, str.mid( 6 ), it ); // remove dupes without ftp://
5391 else if( str.startsWith( file2 ))
5392 hp_removeDupe( l, str.mid( 7 ), it ); // remove dupes without file://
5393 else if( str.startsWith( file ))
5394 hp_removeDupe( l, str.mid( 5 ), it ); // remove dupes without file:
5398 static void hp_removeCommonPrefix( KCompletionMatches& l, const QString& prefix )
5400 for( KCompletionMatches::Iterator it = l.begin();
5401 it != l.end();
5403 if( (*it).value().startsWith( prefix )) {
5404 it = l.erase( it );
5405 continue;
5407 ++it;
5411 // don't include common prefixes like 'http://', i.e. when s == 'h', include
5412 // http://hotmail.com but don't include everything just starting with 'http://'
5413 static void hp_checkCommonPrefixes( KCompletionMatches& matches, const QString& s )
5415 static const char* const prefixes[] = {
5416 "http://",
5417 "https://",
5418 "www.",
5419 "ftp://",
5420 "http://www.",
5421 "https://www.",
5422 "ftp://ftp.",
5423 "file:",
5424 "file://",
5425 NULL };
5426 for( const char* const *pos = prefixes;
5427 *pos != NULL;
5428 ++pos ) {
5429 QString prefix = *pos;
5430 if( prefix.startsWith( s )) {
5431 hp_removeCommonPrefix( matches, prefix );
5436 QStringList KonqMainWindow::historyPopupCompletionItems( const QString& s)
5438 const QString http = "http://";
5439 const QString https = "https://";
5440 const QString www = "http://www.";
5441 const QString wwws = "https://www.";
5442 const QString ftp = "ftp://";
5443 const QString ftpftp = "ftp://ftp.";
5444 const QString file = "file:"; // without /, because people enter /usr etc.
5445 const QString file2 = "file://";
5446 if( s.isEmpty())
5447 return QStringList();
5448 KCompletionMatches matches= s_pCompletion->allWeightedMatches( s );
5449 hp_checkCommonPrefixes( matches, s );
5450 bool checkDuplicates = false;
5451 if ( !s.startsWith( ftp ) ) {
5452 matches += s_pCompletion->allWeightedMatches( ftp + s );
5453 if( QString( "ftp." ).startsWith( s ))
5454 hp_removeCommonPrefix( matches, ftpftp );
5455 checkDuplicates = true;
5457 if ( !s.startsWith( https ) ) {
5458 matches += s_pCompletion->allWeightedMatches( https + s );
5459 if( QString( "www." ).startsWith( s ))
5460 hp_removeCommonPrefix( matches, wwws );
5461 checkDuplicates = true;
5463 if ( !s.startsWith( http )) {
5464 matches += s_pCompletion->allWeightedMatches( http + s );
5465 if( QString( "www." ).startsWith( s ))
5466 hp_removeCommonPrefix( matches, www );
5467 checkDuplicates = true;
5469 if ( !s.startsWith( www ) ) {
5470 matches += s_pCompletion->allWeightedMatches( www + s );
5471 checkDuplicates = true;
5473 if ( !s.startsWith( wwws ) ) {
5474 matches += s_pCompletion->allWeightedMatches( wwws + s );
5475 checkDuplicates = true;
5477 if ( !s.startsWith( ftpftp ) ) {
5478 matches += s_pCompletion->allWeightedMatches( ftpftp + s );
5479 checkDuplicates = true;
5481 if ( !s.startsWith( file ) ) {
5482 matches += s_pCompletion->allWeightedMatches( file + s );
5483 checkDuplicates = true;
5485 if ( !s.startsWith( file2 ) ) {
5486 matches += s_pCompletion->allWeightedMatches( file2 + s );
5487 checkDuplicates = true;
5489 if( checkDuplicates )
5490 hp_removeDuplicates( matches );
5491 QStringList items = matches.list();
5492 if( items.count() == 0
5493 && !s.contains( ':' ) && !s.isEmpty() && s[ 0 ] != '/' )
5495 QString pre = hp_tryPrepend( s );
5496 if( !pre.isNull())
5497 items += pre;
5499 return items;
5502 #ifndef NDEBUG
5503 void KonqMainWindow::dumpViewList()
5505 kDebug(1202) << m_mapViews.count() << "views:";
5507 MapViews::Iterator end = m_mapViews.end();
5508 for (MapViews::Iterator it = m_mapViews.begin(); it != end; ++it) {
5509 KonqView* view = it.value();
5510 kDebug(1202) << view << view->part();
5513 #endif
5515 // KonqFrameContainerBase implementation BEGIN
5517 void KonqMainWindow::insertChildFrame( KonqFrameBase * frame, int /*index*/ )
5519 m_pChildFrame = frame;
5520 m_pActiveChild = frame;
5521 frame->setParentContainer(this);
5522 if ( centralWidget() && centralWidget() != frame->asQWidget() ) {
5523 centralWidget()->setParent( 0 ); // workaround Qt-4.1.2 crash (reported)
5524 setCentralWidget( 0 );
5526 setCentralWidget( frame->asQWidget() );
5529 void KonqMainWindow::childFrameRemoved(KonqFrameBase* frame)
5531 Q_ASSERT(frame == m_pChildFrame);
5532 Q_UNUSED(frame)
5533 m_pChildFrame = 0;
5534 m_pActiveChild = 0;
5537 void KonqMainWindow::saveConfig( KConfigGroup& config, const QString &prefix, const KonqFrameBase::Options &options, KonqFrameBase* docContainer, int id, int depth ) { if( m_pChildFrame ) m_pChildFrame->saveConfig( config, prefix, options, docContainer, id, depth); }
5539 void KonqMainWindow::copyHistory( KonqFrameBase *other ) { if( m_pChildFrame ) m_pChildFrame->copyHistory( other ); }
5541 void KonqMainWindow::setTitle( const QString &/*title*/ , QWidget* /*sender*/) { return; }
5542 void KonqMainWindow::setTabIcon( const KUrl &/*url*/, QWidget* /*sender*/ ) { return; }
5544 QWidget* KonqMainWindow::asQWidget() { return this; }
5546 KonqFrameBase::FrameType KonqMainWindow::frameType() const { return KonqFrameBase::MainWindow; }
5548 KonqFrameBase* KonqMainWindow::childFrame()const { return m_pChildFrame; }
5550 void KonqMainWindow::setActiveChild( KonqFrameBase* /*activeChild*/ ) { return; }
5552 bool KonqMainWindow::isMimeTypeAssociatedWithSelf( const QString &mimeType )
5554 return isMimeTypeAssociatedWithSelf( mimeType, KMimeTypeTrader::self()->preferredService( mimeType, "Application" ) );
5557 bool KonqMainWindow::isMimeTypeAssociatedWithSelf( const QString &/*mimeType*/, const KService::Ptr &offer )
5559 // Prevention against user stupidity : if the associated app for this mimetype
5560 // is konqueror/kfmclient, then we'll loop forever. So we have to
5561 // 1) force embedding first, if that works we're ok
5562 // 2) check what KRun is going to do before calling it.
5563 return ( offer && ( offer->desktopEntryName() == "konqueror" ||
5564 offer->exec().trimmed().startsWith( "kfmclient" ) ) );
5567 bool KonqMainWindow::refuseExecutingKonqueror(const QString& mimeType)
5569 if ( activeViewsNotLockedCount() > 0 ) { // if I lock the only view, then there's no error: open links in a new window
5570 KMessageBox::error( this, i18n("There appears to be a configuration error. You have associated Konqueror with %1, but it cannot handle this file type.", mimeType));
5571 return true; // we refuse indeed
5573 return false; // no error
5576 // KonqFrameContainerBase implementation END
5578 void KonqMainWindow::setPreloadedFlag( bool preloaded )
5580 if( s_preloaded == preloaded )
5581 return;
5582 s_preloaded = preloaded;
5583 if( s_preloaded )
5585 kapp->disableSessionManagement(); // don't restore preloaded konqy's
5586 KonqSessionManager::self()->disableAutosave(); // don't save sessions
5587 return; // was registered before calling this
5589 delete s_preloadedWindow; // preloaded state was abandoned without reusing the window
5590 s_preloadedWindow = NULL;
5591 kapp->enableSessionManagement(); // enable SM again
5592 KonqSessionManager::self()->enableAutosave(); // enable session saving again
5593 QDBusInterface ref( "org.kde.kded", "/modules/konqy_preloader", "org.kde.konqueror.Preloader", QDBusConnection::sessionBus() );
5594 ref.call( "unregisterPreloadedKonqy", QDBusConnection::sessionBus().baseService() );
5597 void KonqMainWindow::setPreloadedWindow( KonqMainWindow* window )
5599 s_preloadedWindow = window;
5600 if( window == NULL )
5601 return;
5602 window->viewManager()->clear();
5603 KIO::Scheduler::unregisterWindow( window );
5606 // used by preloading - this KonqMainWindow will be reused, reset everything
5607 // that won't be reset by loading a profile
5608 void KonqMainWindow::resetWindow()
5610 #ifdef Q_WS_X11
5611 char data[ 1 ];
5612 // empty append to get current X timestamp
5613 QWidget tmp_widget;
5614 XChangeProperty( QX11Info::display(), tmp_widget.winId(), XA_WM_CLASS, XA_STRING, 8,
5615 PropModeAppend, (unsigned char*) &data, 0 );
5616 XEvent ev;
5617 XWindowEvent( QX11Info::display(), tmp_widget.winId(), PropertyChangeMask, &ev );
5618 long x_time = ev.xproperty.time;
5619 // bad hack - without updating the _KDE_NET_WM_USER_CREATION_TIME property,
5620 // KWin will apply don't_steal_focus to this window, and will not make it active
5621 // (shows mainly with 'konqueror --preload')
5622 static Atom atom = XInternAtom( QX11Info::display(), "_KDE_NET_WM_USER_CREATION_TIME", False );
5623 XChangeProperty( QX11Info::display(), winId(), atom, XA_CARDINAL, 32,
5624 PropModeReplace, (unsigned char *) &x_time, 1);
5625 // reset also user time, so that this window won't have _NET_WM_USER_TIME set
5626 QX11Info::setAppUserTime(CurrentTime);
5628 static Atom atom3 = XInternAtom( QX11Info::display(), "_NET_WM_USER_TIME", False );
5629 XDeleteProperty( QX11Info::display(), winId(), atom3 );
5630 #endif
5631 // Qt remembers the iconic state if the window was withdrawn while on another virtual desktop
5632 setWindowState( windowState() & ~Qt::WindowMinimized );
5633 ignoreInitialGeometry();
5636 bool KonqMainWindow::event( QEvent* e )
5638 if( e->type() == QEvent::DeferredDelete )
5640 // since the preloading code tries to reuse KonqMainWindow,
5641 // the last window shouldn't be really deleted, but only hidden
5642 // deleting WDestructiveClose windows is done using deleteLater(),
5643 // so catch QEvent::DeferredDelete and check if this window should stay
5644 if( stayPreloaded())
5646 setAttribute(Qt::WA_DeleteOnClose); // was reset before deleteLater()
5647 return true; // no deleting
5650 } else if ( e->type() == QEvent::StatusTip) {
5651 if (m_currentView && m_currentView->frame()->statusbar()) {
5652 KonqFrameStatusBar *statusBar = m_currentView->frame()->statusbar();
5653 statusBar->message(static_cast<QStatusTipEvent*>(e)->tip());
5657 if ( KonqFileSelectionEvent::test( e ) ||
5658 KonqFileMouseOverEvent::test( e ) )
5660 // Forward the event to all views
5661 MapViews::ConstIterator it = m_mapViews.constBegin();
5662 MapViews::ConstIterator end = m_mapViews.constEnd();
5663 for (; it != end; ++it )
5664 QApplication::sendEvent( (*it)->part(), e );
5665 return true;
5667 if ( KParts::OpenUrlEvent::test( e ) )
5669 KParts::OpenUrlEvent * ev = static_cast<KParts::OpenUrlEvent*>(e);
5671 // Forward the event to all views
5672 MapViews::ConstIterator it = m_mapViews.constBegin();
5673 MapViews::ConstIterator end = m_mapViews.constEnd();
5674 for (; it != end; ++it )
5676 // Don't resend to sender
5677 if (it.key() != ev->part())
5679 //kDebug(1202) << "Sending event to view" << it.key()->metaObject()->className();
5680 QApplication::sendEvent( it.key(), e );
5684 return KParts::MainWindow::event( e );
5687 bool KonqMainWindow::stayPreloaded()
5689 #ifdef Q_WS_X11
5690 // last window?
5691 if( mainWindowList()->count() > 1 )
5692 return false;
5693 // not running in full KDE environment?
5694 if( getenv( "KDE_FULL_SESSION" ) == NULL || getenv( "KDE_FULL_SESSION" )[ 0 ] == '\0' )
5695 return false;
5696 // not the same user like the one running the session (most likely we're run via sudo or something)
5697 if( getenv( "KDE_SESSION_UID" ) != NULL && uid_t( atoi( getenv( "KDE_SESSION_UID" ))) != getuid())
5698 return false;
5699 if( KonqSettings::maxPreloadCount() == 0 )
5700 return false;
5701 viewManager()->clear(); // reduce resource usage before checking it
5702 if( !checkPreloadResourceUsage())
5703 return false;
5704 QDBusInterface ref( "org.kde.kded", "/modules/konqy_preloader", "org.kde.konqueror.Preloader", QDBusConnection::sessionBus() );
5705 QX11Info info;
5706 QDBusReply<bool> retVal = ref.call( QDBus::Block, "registerPreloadedKonqy", QDBusConnection::sessionBus().baseService(), info.screen());
5707 if ( !retVal )
5709 return false;
5711 KonqMainWindow::setPreloadedFlag( true );
5712 kDebug(1202) << "Konqy kept for preloading:" << QDBusConnection::sessionBus().baseService();
5713 KonqMainWindow::setPreloadedWindow( this );
5714 return true;
5715 #else
5716 return false;
5717 #endif
5720 // try to avoid staying running when leaking too much memory
5721 // this is checked by using mallinfo() and comparing
5722 // memory usage during konqy startup and now, if the difference
5723 // is too large -> leaks -> quit
5724 // also, if this process is running for too long, or has been
5725 // already reused too many times -> quit, just in case
5726 bool KonqMainWindow::checkPreloadResourceUsage()
5729 #ifndef NDEBUG
5730 isatty( STDIN_FILENO ) ||
5731 #endif
5732 isatty( STDOUT_FILENO ) || isatty( STDERR_FILENO ))
5734 kDebug(1202) << "Running from tty, not keeping for preloading";
5735 return false;
5737 int limit;
5738 int usage = current_memory_usage( &limit );
5739 kDebug(1202) << "Memory usage increase: " << ( usage - s_initialMemoryUsage )
5740 << " (" << usage << "/" << s_initialMemoryUsage << "), increase limit: " << limit;
5741 int max_allowed_usage = s_initialMemoryUsage + limit;
5742 if( usage > max_allowed_usage ) // too much memory used?
5744 kDebug(1202) << "Not keeping for preloading due to high memory usage";
5745 return false;
5747 // working memory usage test ( usage != 0 ) makes others less strict
5748 if( ++s_preloadUsageCount > ( usage != 0 ? 100 : 10 )) // reused too many times?
5750 kDebug(1202) << "Not keeping for preloading due to high usage count";
5751 return false;
5753 if( time( NULL ) > s_startupTime + 60 * 60 * ( usage != 0 ? 4 : 1 )) // running for too long?
5755 kDebug(1202) << "Not keeping for preloading due to long usage time";
5756 return false;
5758 return true;
5761 static int current_memory_usage( int* limit )
5763 #ifdef __linux__ //krazy:exclude=cpp
5764 // Check whole memory usage - VmSize
5765 QFile f( QString::fromLatin1( "/proc/%1/statm" ).arg(getpid()) );
5766 if( f.open( QIODevice::ReadOnly ))
5768 QByteArray buffer; buffer.resize( 100 );
5769 const int bytes = f.readLine( buffer.data(), buffer.size()-1 );
5770 if ( bytes != -1 )
5772 QString line = QString::fromLatin1( buffer ).trimmed();
5773 const int usage = line.section( ' ', 0, 0 ).toInt();
5774 if( usage > 0 )
5776 int pagesize = sysconf (_SC_PAGE_SIZE);
5777 if( pagesize < 0 )
5778 pagesize = 4096;
5779 if( limit != NULL )
5780 *limit = 16 * 1024 * 1024;
5781 return usage * pagesize;
5785 kWarning() << "Couldn't read VmSize from /proc/*/statm." ;
5786 #endif
5787 // Check malloc() usage - very imprecise, but better than nothing.
5788 int usage_sum = 0;
5789 #if defined(KDE_MALLINFO_STDLIB) || defined(KDE_MALLINFO_MALLOC)
5790 struct mallinfo m = mallinfo();
5791 #ifdef KDE_MALLINFO_FIELD_hblkhd
5792 usage_sum += m.hblkhd;
5793 #endif
5794 #ifdef KDE_MALLINFO_FIELD_uordblks
5795 usage_sum += m.uordblks;
5796 #endif
5797 #ifdef KDE_MALLINFO_FIELD_usmblks
5798 usage_sum += m.usmblks;
5799 #endif
5800 // unlike /proc , this doesn't include things like size of dlopened modules,
5801 // and also doesn't include malloc overhead
5802 if( limit != NULL )
5803 *limit = 6 * 1024 * 1024;
5804 #endif
5805 return usage_sum;
5808 void KonqMainWindow::slotUndoTextChanged( const QString & newText )
5810 m_paUndo->setText(newText);
5813 // outlined because of QPointer and gcc3
5814 KonqView * KonqMainWindow::currentView() const
5816 return m_currentView;
5819 bool KonqMainWindow::accept( KonqFrameVisitor* visitor )
5821 if ( !visitor->visit( this ) )
5822 return false;
5823 if ( m_pChildFrame && !m_pChildFrame->accept( visitor ) )
5824 return false;
5825 if ( !visitor->endVisit( this ) )
5826 return false;
5827 return true;
5830 bool KonqMainWindow::hasViewWithMimeType(const QString& mimeType) const
5832 MapViews::const_iterator it = m_mapViews.constBegin();
5833 const MapViews::const_iterator end = m_mapViews.constEnd();
5834 for (; it != end; ++it) {
5835 if ((*it)->supportsMimeType(mimeType)) {
5836 //kDebug(1202) << *it << "supports" << mimeType << "!";
5837 return true;
5840 return false;
5843 void KonqMainWindow::applyWindowSizeFromProfile(const KConfigGroup& profileGroup)
5845 // KMainWindow::restoreWindowSize is protected so this logic can't move to KonqViewManager
5846 const QSize size = KonqViewManager::readDefaultSize(profileGroup, this); // example: "Width=80%"
5847 if (size.isValid())
5848 resize(size);
5849 restoreWindowSize(profileGroup); // example: "Width 1400=1120"
5852 #include "konqmainwindow.moc"