mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-25 02:45:38 +00:00
Launch documents from external sources in new tabs
FIXED-IN: 4.13.0 BUGS: 331872 BUGS: 332238 REVIEW: 116700
This commit is contained in:
parent
a7f3a1ac37
commit
89fd56c23b
14
part.cpp
14
part.cpp
|
@ -346,6 +346,7 @@ m_cliPresentation(false), m_cliPrint(false), m_embedMode(detectEmbedMode(parentW
|
|||
|
||||
m_sidebar = new Sidebar( parentWidget );
|
||||
setWidget( m_sidebar );
|
||||
connect( m_sidebar, SIGNAL(urlsDropped(KUrl::List)), SLOT(handleDroppedUrls(KUrl::List)) );
|
||||
|
||||
// build the document
|
||||
m_document = new Okular::Document(widget());
|
||||
|
@ -382,7 +383,6 @@ m_cliPresentation(false), m_cliPrint(false), m_embedMode(detectEmbedMode(parentW
|
|||
m_searchWidget = new SearchWidget( thumbsBox, m_document );
|
||||
m_thumbnailList = new ThumbnailList( thumbsBox, m_document );
|
||||
// ThumbnailController * m_tc = new ThumbnailController( thumbsBox, m_thumbnailList );
|
||||
connect( m_thumbnailList, SIGNAL(urlDropped(KUrl)), SLOT(openUrlFromDocument(KUrl)) );
|
||||
connect( m_thumbnailList, SIGNAL(rightClick(const Okular::Page*,QPoint)), this, SLOT(slotShowMenu(const Okular::Page*,QPoint)) );
|
||||
tbIndex = m_sidebar->addItem( thumbsBox, KIcon( "view-preview" ), i18n("Thumbnails") );
|
||||
m_sidebar->setCurrentIndex( tbIndex );
|
||||
|
@ -433,7 +433,6 @@ m_cliPresentation(false), m_cliPrint(false), m_embedMode(detectEmbedMode(parentW
|
|||
m_pageView = new PageView( rightContainer, m_document );
|
||||
QMetaObject::invokeMethod( m_pageView, "setFocus", Qt::QueuedConnection ); //usability setting
|
||||
// m_splitter->setFocusProxy(m_pageView);
|
||||
connect( m_pageView, SIGNAL(urlDropped(KUrl)), SLOT(openUrlFromDocument(KUrl)));
|
||||
connect( m_pageView, SIGNAL(rightClick(const Okular::Page*,QPoint)), this, SLOT(slotShowMenu(const Okular::Page*,QPoint)) );
|
||||
connect( m_document, SIGNAL(error(QString,int)), m_pageView, SLOT(errorMessage(QString,int)) );
|
||||
connect( m_document, SIGNAL(warning(QString,int)), m_pageView, SLOT(warningMessage(QString,int)) );
|
||||
|
@ -989,6 +988,17 @@ void Part::openUrlFromBookmarks(const KUrl &_url)
|
|||
openUrl( url );
|
||||
}
|
||||
|
||||
void Part::handleDroppedUrls( const KUrl::List& urls )
|
||||
{
|
||||
if( m_embedMode != NativeShellMode || !openNewFilesInTabs() )
|
||||
{
|
||||
openUrlFromDocument( urls.first() );
|
||||
return;
|
||||
}
|
||||
|
||||
emit urlsDropped( urls );
|
||||
}
|
||||
|
||||
void Part::slotJobStarted(KIO::Job *job)
|
||||
{
|
||||
if (job)
|
||||
|
|
2
part.h
2
part.h
|
@ -158,6 +158,7 @@ class OKULAR_PART_EXPORT Part : public KParts::ReadWritePart, public Okular::Doc
|
|||
void viewerMenuStateChange(bool enabled);
|
||||
void enableCloseAction(bool enable);
|
||||
void mimeTypeChanged(KMimeType::Ptr mimeType);
|
||||
void urlsDropped( const KUrl::List& urls );
|
||||
|
||||
protected:
|
||||
// reimplemented from KParts::ReadWritePart
|
||||
|
@ -176,6 +177,7 @@ class OKULAR_PART_EXPORT Part : public KParts::ReadWritePart, public Okular::Doc
|
|||
// connected to actions
|
||||
void openUrlFromDocument(const KUrl &url);
|
||||
void openUrlFromBookmarks(const KUrl &url);
|
||||
void handleDroppedUrls( const KUrl::List& urls );
|
||||
void slotGoToPage();
|
||||
void slotHistoryBack();
|
||||
void slotHistoryNext();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <klocale.h>
|
||||
#include <QtDBus/qdbusinterface.h>
|
||||
#include <QTextStream>
|
||||
#include <kwindowsystem.h>
|
||||
#include "aboutdata.h"
|
||||
#include "shellutils.h"
|
||||
|
||||
|
@ -44,6 +45,77 @@ static bool attachUniqueInstance(KCmdLineArgs* args)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Ask an existing non-unique instance to open new tabs
|
||||
static bool attachExistingInstance( KCmdLineArgs* args )
|
||||
{
|
||||
if( args->count() < 1 )
|
||||
return false;
|
||||
|
||||
const QStringList services = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
|
||||
|
||||
// Don't match the service without trailing "-" (unique instance)
|
||||
const QString pattern = "org.kde.okular-";
|
||||
const QString myPid = QString::number( kapp->applicationPid() );
|
||||
QScopedPointer<QDBusInterface> bestService;
|
||||
const int desktop = KWindowSystem::currentDesktop();
|
||||
|
||||
// Select the first instance that isn't us (metric may change in future)
|
||||
foreach( const QString& service, services )
|
||||
{
|
||||
if( service.startsWith(pattern) && !service.endsWith(myPid) )
|
||||
{
|
||||
bestService.reset( new QDBusInterface(service,"/okularshell","org.kde.okular") );
|
||||
|
||||
// Find a window that can handle our documents
|
||||
const QDBusReply<bool> reply = bestService->call( "canOpenDocs", args->count(), desktop );
|
||||
if( reply.isValid() && reply.value() )
|
||||
break;
|
||||
|
||||
bestService.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if( !bestService )
|
||||
return false;
|
||||
|
||||
for( int i = 0; i < args->count(); ++i )
|
||||
{
|
||||
QString arg = args->arg( i );
|
||||
|
||||
// Copy stdin to temporary file which can be opened by the existing
|
||||
// window. The temp file is automatically deleted after it has been
|
||||
// opened. Not sure if this behavior is safe on all platforms.
|
||||
QScopedPointer<QTemporaryFile> tempFile;
|
||||
if( arg == "-" )
|
||||
{
|
||||
tempFile.reset( new QTemporaryFile );
|
||||
QFile stdinFile;
|
||||
if( !tempFile->open() || !stdinFile.open(stdin,QIODevice::ReadOnly) )
|
||||
return false;
|
||||
|
||||
const size_t bufSize = 1024*1024;
|
||||
QScopedPointer<char,QScopedPointerArrayDeleter<char> > buf( new char[bufSize] );
|
||||
size_t bytes;
|
||||
do
|
||||
{
|
||||
bytes = stdinFile.read( buf.data(), bufSize );
|
||||
tempFile->write( buf.data(), bytes );
|
||||
} while( bytes != 0 );
|
||||
|
||||
arg = tempFile->fileName();
|
||||
}
|
||||
|
||||
// Returns false if it can't fit another document
|
||||
const QDBusReply<bool> reply = bestService->call( "openDocument", arg );
|
||||
if( !reply.isValid() || !reply.value() )
|
||||
return false;
|
||||
}
|
||||
|
||||
bestService->call( "tryRaise" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
KAboutData about = okularAboutData( "okular", I18N_NOOP( "Okular" ) );
|
||||
|
@ -69,19 +141,14 @@ int main(int argc, char** argv)
|
|||
// no session.. just start up normally
|
||||
KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
|
||||
|
||||
// try to attach the "unique" session: if we succeed, do nothing more and exit
|
||||
if (attachUniqueInstance(args))
|
||||
// try to attach to existing session, unique or not
|
||||
if (attachUniqueInstance(args) || attachExistingInstance(args))
|
||||
{
|
||||
args->clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args->count() == 0)
|
||||
{
|
||||
Shell* widget = new Shell(args);
|
||||
widget->show();
|
||||
}
|
||||
else if (args->isSet( "unique" ) && args->count() > 1)
|
||||
if (args->isSet( "unique" ) && args->count() > 1)
|
||||
{
|
||||
QTextStream stream(stderr);
|
||||
stream << i18n( "Error: Can't open more than one document with the --unique switch" ) << endl;
|
||||
|
@ -89,11 +156,18 @@ int main(int argc, char** argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < args->count(); ++i)
|
||||
Shell* shell = new Shell( args );
|
||||
shell->show();
|
||||
for( int i = 0; i < args->count(); )
|
||||
{
|
||||
if( shell->openDocument(args->arg(i)) )
|
||||
++i;
|
||||
else
|
||||
{
|
||||
Shell* widget = new Shell(args, i);
|
||||
widget->show();
|
||||
shell = new Shell( args );
|
||||
shell->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <kwindowsystem.h>
|
||||
#include <ktabwidget.h>
|
||||
#include <kxmlguifactory.h>
|
||||
#include <QDragMoveEvent>
|
||||
|
||||
#ifdef KActivities_FOUND
|
||||
#include <KActivities/ResourceInstance>
|
||||
|
@ -104,6 +105,8 @@ void Shell::init()
|
|||
m_tabWidget->setDocumentMode( true );
|
||||
connect( m_tabWidget, SIGNAL(currentChanged(int)), SLOT(setActiveTab(int)) );
|
||||
connect( m_tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(closeTab(int)) );
|
||||
connect( m_tabWidget, SIGNAL(testCanDecode(const QDragMoveEvent*,bool&)), SLOT(testTabDrop(const QDragMoveEvent*,bool&)) );
|
||||
connect( m_tabWidget, SIGNAL(receivedDropEvent(QDropEvent*)), SLOT(handleTabDrop(QDropEvent*)) );
|
||||
|
||||
setCentralWidget( m_tabWidget );
|
||||
|
||||
|
@ -119,11 +122,6 @@ void Shell::init()
|
|||
|
||||
readSettings();
|
||||
|
||||
if (m_args && m_args->isSet("unique") && m_args->count() == 1)
|
||||
{
|
||||
QDBusConnection::sessionBus().registerService("org.kde.okular");
|
||||
}
|
||||
|
||||
m_unique = false;
|
||||
if (m_args && m_args->isSet("unique") && m_args->count() <= 1)
|
||||
{
|
||||
|
@ -171,6 +169,43 @@ Shell::~Shell()
|
|||
m_args->clear();
|
||||
}
|
||||
|
||||
// Open a new document if we have space for it
|
||||
// This can hang if called on a unique instance and openUrl pops a messageBox
|
||||
bool Shell::openDocument( const QString& doc )
|
||||
{
|
||||
if( m_tabs.size() <= 0 )
|
||||
return false;
|
||||
|
||||
KParts::ReadWritePart* const part = m_tabs[0].part;
|
||||
|
||||
// Return false if we can't open new tabs and the only part is occupied
|
||||
if( !dynamic_cast<Okular::ViewerInterface*>(part)->openNewFilesInTabs()
|
||||
&& !part->url().isEmpty() )
|
||||
return false;
|
||||
|
||||
openUrl( ShellUtils::urlFromArg(doc,ShellUtils::qfileExistFunc()) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Shell::canOpenDocs( int numDocs, int desktop )
|
||||
{
|
||||
if( m_tabs.size() <= 0 || numDocs <= 0 || m_unique )
|
||||
return false;
|
||||
|
||||
KParts::ReadWritePart* const part = m_tabs[0].part;
|
||||
const bool allowTabs = dynamic_cast<Okular::ViewerInterface*>(part)->openNewFilesInTabs();
|
||||
|
||||
if( !allowTabs && (numDocs > 1 || !part->url().isEmpty()) )
|
||||
return false;
|
||||
|
||||
const KWindowInfo winfo( window()->effectiveWinId(), KWindowSystem::WMDesktop );
|
||||
if( winfo.desktop() != desktop )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shell::openUrl( const KUrl & url )
|
||||
{
|
||||
const int activeTab = m_tabWidget->currentIndex();
|
||||
|
@ -382,10 +417,7 @@ void Shell::slotQuit()
|
|||
|
||||
void Shell::tryRaise()
|
||||
{
|
||||
if (m_unique)
|
||||
{
|
||||
KWindowSystem::forceActiveWindow( window()->effectiveWinId() );
|
||||
}
|
||||
KWindowSystem::forceActiveWindow( window()->effectiveWinId() );
|
||||
}
|
||||
|
||||
// only called when starting the program
|
||||
|
@ -521,6 +553,7 @@ void Shell::connectPart( QObject* part )
|
|||
connect( part, SIGNAL(enablePrintAction(bool)), this, SLOT(setPrintEnabled(bool)));
|
||||
connect( part, SIGNAL(enableCloseAction(bool)), this, SLOT(setCloseEnabled(bool)));
|
||||
connect( part, SIGNAL(mimeTypeChanged(KMimeType::Ptr)), this, SLOT(setTabIcon(KMimeType::Ptr)));
|
||||
connect( part, SIGNAL(urlsDropped(KUrl::List)), this, SLOT(handleDroppedUrls(KUrl::List)) );
|
||||
}
|
||||
|
||||
void Shell::print()
|
||||
|
@ -593,6 +626,26 @@ int Shell::findTabIndex( QObject* sender )
|
|||
return -1;
|
||||
}
|
||||
|
||||
void Shell::handleDroppedUrls( const KUrl::List& urls )
|
||||
{
|
||||
foreach( const KUrl& url, urls )
|
||||
{
|
||||
openUrl( url );
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::testTabDrop( const QDragMoveEvent* event, bool& accept )
|
||||
{
|
||||
accept = KUrl::List::canDecode( event->mimeData() );
|
||||
}
|
||||
|
||||
void Shell::handleTabDrop( QDropEvent* event )
|
||||
{
|
||||
const KUrl::List list = KUrl::List::fromMimeData( event->mimeData() );
|
||||
if( !list.isEmpty() )
|
||||
handleDroppedUrls( list );
|
||||
}
|
||||
|
||||
#include "shell.moc"
|
||||
|
||||
/* kate: replace-tabs on; indent-width 4; */
|
||||
|
|
|
@ -63,6 +63,8 @@ public slots:
|
|||
void slotQuit();
|
||||
|
||||
Q_SCRIPTABLE Q_NOREPLY void tryRaise();
|
||||
Q_SCRIPTABLE bool openDocument( const QString& doc );
|
||||
Q_SCRIPTABLE bool canOpenDocs( int numDocs, int desktop );
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -98,12 +100,15 @@ private slots:
|
|||
void setPrintEnabled( bool enabled );
|
||||
void setCloseEnabled( bool enabled );
|
||||
void setTabIcon( KMimeType::Ptr mimeType );
|
||||
void handleDroppedUrls( const KUrl::List& urls );
|
||||
|
||||
// Tab event handlers
|
||||
void setActiveTab( int tab );
|
||||
void closeTab( int tab );
|
||||
void activateNextTab();
|
||||
void activatePrevTab();
|
||||
void testTabDrop( const QDragMoveEvent* event, bool& accept );
|
||||
void handleTabDrop( QDropEvent* event );
|
||||
|
||||
signals:
|
||||
void restoreDocument(const KConfigGroup &group);
|
||||
|
|
|
@ -260,7 +260,7 @@ OkularTTS* PageViewPrivate::tts()
|
|||
* Code weight (in rows) and meaning:
|
||||
* 160 - constructor and creating actions plus their connected slots (empty stuff)
|
||||
* 70 - DocumentObserver inherited methodes (important)
|
||||
* 550 - events: mouse, keyboard, drag/drop
|
||||
* 550 - events: mouse, keyboard, drag
|
||||
* 170 - slotRelayoutPages: set contents of the scrollview on continuous/single modes
|
||||
* 100 - zoom: zooming pages in different ways, keeping update the toolbar actions, etc..
|
||||
* other misc functions: only slotRequestVisiblePixmaps and pickItemOnPoint noticeable,
|
||||
|
@ -362,12 +362,11 @@ PageView::PageView( QWidget *parent, Okular::Document *document )
|
|||
|
||||
setObjectName( QLatin1String( "okular::pageView" ) );
|
||||
|
||||
// viewport setup: setup focus, accept drops and track mouse
|
||||
// viewport setup: setup focus, and track mouse
|
||||
viewport()->setFocusProxy( this );
|
||||
viewport()->setFocusPolicy( Qt::StrongFocus );
|
||||
viewport()->setAttribute( Qt::WA_OpaquePaintEvent );
|
||||
viewport()->setAttribute( Qt::WA_NoSystemBackground );
|
||||
setAcceptDrops( true );
|
||||
viewport()->setMouseTracking( true );
|
||||
viewport()->setAutoFillBackground( false );
|
||||
// the apparently "magic" value of 20 is the same used internally in QScrollArea
|
||||
|
@ -3088,26 +3087,6 @@ void PageView::wheelEvent( QWheelEvent *e )
|
|||
updateCursor();
|
||||
}
|
||||
|
||||
void PageView::dragEnterEvent( QDragEnterEvent * ev )
|
||||
{
|
||||
ev->accept();
|
||||
}
|
||||
|
||||
void PageView::dragMoveEvent( QDragMoveEvent * ev )
|
||||
{
|
||||
ev->accept();
|
||||
}
|
||||
|
||||
void PageView::dropEvent( QDropEvent * ev )
|
||||
{
|
||||
if ( KUrl::List::canDecode( ev->mimeData() ) )
|
||||
{
|
||||
const KUrl::List list = KUrl::List::fromMimeData( ev->mimeData() );
|
||||
if ( !list.isEmpty() )
|
||||
emit urlDropped( list.first() );
|
||||
}
|
||||
}
|
||||
|
||||
bool PageView::viewportEvent( QEvent * e )
|
||||
{
|
||||
if ( e->type() == QEvent::ToolTip && Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::Browse )
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
class KAction;
|
||||
class KActionCollection;
|
||||
class KMenu;
|
||||
class KUrl;
|
||||
|
||||
namespace Okular {
|
||||
class Action;
|
||||
|
@ -136,7 +135,6 @@ Q_OBJECT
|
|||
void openAnnotationWindow( Okular::Annotation *annotation, int pageNumber );
|
||||
|
||||
signals:
|
||||
void urlDropped( const KUrl& );
|
||||
void rightClick( const Okular::Page *, const QPoint & );
|
||||
void mouseBackButtonClick();
|
||||
void mouseForwardButtonClick();
|
||||
|
@ -151,11 +149,6 @@ Q_OBJECT
|
|||
void inputMethodEvent( QInputMethodEvent * );
|
||||
void wheelEvent( QWheelEvent* );
|
||||
|
||||
// drag and drop related events
|
||||
void dragEnterEvent( QDragEnterEvent* );
|
||||
void dragMoveEvent( QDragMoveEvent* );
|
||||
void dropEvent( QDropEvent* );
|
||||
|
||||
void paintEvent( QPaintEvent *e );
|
||||
void tabletEvent (QTabletEvent *e );
|
||||
void mouseMoveEvent( QMouseEvent *e );
|
||||
|
|
|
@ -449,6 +449,7 @@ Sidebar::Sidebar( QWidget *parent )
|
|||
mainlay->setSpacing( 0 );
|
||||
|
||||
setAutoFillBackground( true );
|
||||
setAcceptDrops( true );
|
||||
|
||||
d->list = new SidebarListWidget( this );
|
||||
mainlay->addWidget( d->list );
|
||||
|
@ -753,4 +754,16 @@ void Sidebar::appearanceChanged()
|
|||
d->sideDelegate->updateBrushCache();
|
||||
}
|
||||
|
||||
void Sidebar::dragEnterEvent( QDragEnterEvent* event )
|
||||
{
|
||||
event->setAccepted( KUrl::List::canDecode(event->mimeData()) );
|
||||
}
|
||||
|
||||
void Sidebar::dropEvent( QDropEvent* event )
|
||||
{
|
||||
const KUrl::List list = KUrl::List::fromMimeData( event->mimeData() );
|
||||
if( !list.isEmpty() )
|
||||
emit urlsDropped( list );
|
||||
}
|
||||
|
||||
#include "sidebar.moc"
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define _SIDEBAR_H_
|
||||
|
||||
#include <qwidget.h>
|
||||
#include <KUrl>
|
||||
|
||||
class QIcon;
|
||||
class QListWidgetItem;
|
||||
|
@ -41,6 +42,13 @@ class Sidebar : public QWidget
|
|||
void setCollapsed( bool collapsed );
|
||||
bool isCollapsed() const;
|
||||
|
||||
signals:
|
||||
void urlsDropped( const KUrl::List& urls );
|
||||
|
||||
protected:
|
||||
void dragEnterEvent( QDragEnterEvent* event );
|
||||
void dropEvent( QDropEvent* event );
|
||||
|
||||
private slots:
|
||||
void itemClicked( QListWidgetItem *item );
|
||||
void splitterMoved( int pos, int index );
|
||||
|
|
|
@ -208,8 +208,6 @@ ThumbnailList::ThumbnailList( QWidget *parent, Okular::Document *document )
|
|||
|
||||
setAttribute( Qt::WA_StaticContents );
|
||||
|
||||
setAcceptDrops( true );
|
||||
|
||||
viewport()->setBackgroundRole( QPalette::Base );
|
||||
|
||||
setWidget( d );
|
||||
|
@ -600,21 +598,6 @@ void ThumbnailListPrivate::viewportResizeEvent( QResizeEvent * e )
|
|||
// update Thumbnails since width has changed or height has increased
|
||||
delayedRequestVisiblePixmaps( 500 );
|
||||
}
|
||||
|
||||
void ThumbnailList::dragEnterEvent( QDragEnterEvent * ev )
|
||||
{
|
||||
ev->accept();
|
||||
}
|
||||
|
||||
void ThumbnailList::dropEvent( QDropEvent * ev )
|
||||
{
|
||||
if ( KUrl::List::canDecode( ev->mimeData() ) )
|
||||
{
|
||||
const KUrl::List list = KUrl::List::fromMimeData( ev->mimeData() );
|
||||
if ( !list.isEmpty() )
|
||||
emit urlDropped( list.first() );
|
||||
}
|
||||
}
|
||||
//END widget events
|
||||
|
||||
//BEGIN internal SLOTS
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "core/observer.h"
|
||||
|
||||
class KUrl;
|
||||
class ThumbnailListPrivate;
|
||||
|
||||
namespace Okular {
|
||||
|
@ -63,12 +62,7 @@ Q_OBJECT
|
|||
// catch the viewport event and filter them if necessary
|
||||
bool viewportEvent( QEvent * );
|
||||
|
||||
// file drop related events (an url may be dropped even here)
|
||||
void dragEnterEvent( QDragEnterEvent* );
|
||||
void dropEvent( QDropEvent* );
|
||||
|
||||
signals:
|
||||
void urlDropped( const KUrl& );
|
||||
void rightClick( const Okular::Page *, const QPoint & );
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue