Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Utilities
Kate
Commits
2cda9f65
Commit
2cda9f65
authored
Sep 18, 2022
by
Eric Armbruster
🍁
Browse files
Adapt welcomeview from Okular for Kate
parent
97f28219
Changes
10
Hide whitespace changes
Inline
Side-by-side
apps/lib/CMakeLists.txt
View file @
2cda9f65
...
...
@@ -66,7 +66,7 @@ if (TARGET KUserFeedbackWidgets)
target_compile_definitions
(
kateprivate PUBLIC -DWITH_KUSERFEEDBACK
)
endif
()
ki18n_wrap_ui
(
kateprivate ui/sessionconfigwidget.ui
ui/
welcome.ui session/katesessionmanagedialog.ui
)
ki18n_wrap_ui
(
kateprivate ui/sessionconfigwidget.ui welcome
view
.ui session/katesessionmanagedialog.ui
)
target_sources
(
kateprivate
...
...
@@ -97,7 +97,6 @@ target_sources(
katesplitter.cpp
kateviewmanager.cpp
kateviewspace.cpp
katewelcomeview.cpp
tabmimedata.cpp
kateoutputview.cpp
...
...
@@ -119,6 +118,9 @@ target_sources(
diff/gitdiff.cpp
filehistorywidget.cpp
recentitemsmodel.cpp
welcomeview.cpp
)
if
(
BUILD_TESTING
)
...
...
apps/lib/katemainwindow.cpp
View file @
2cda9f65
...
...
@@ -75,6 +75,7 @@
#include
<QToolButton>
#include
"diffwidget.h"
#include
"welcomeview.h"
#include
<ktexteditor/sessionconfiginterface.h>
...
...
@@ -307,6 +308,8 @@ void KateMainWindow::setupActions()
m_fileOpenRecent
->
setMaxItems
(
KateConfigDialog
::
recentFilesMaxCount
());
actionCollection
()
->
addAction
(
m_fileOpenRecent
->
objectName
(),
m_fileOpenRecent
);
m_fileOpenRecent
->
setWhatsThis
(
i18n
(
"This lists files which you have opened recently, and allows you to easily open them again."
));
connect
(
m_fileOpenRecent
,
&
KRecentFilesAction
::
recentListCleared
,
this
,
&
KateMainWindow
::
refreshRecentsOnWelcomeView
);
connect
(
m_welcomeView
,
&
WelcomeView
::
forgetAllRecents
,
m_fileOpenRecent
,
&
KRecentFilesAction
::
clear
);
a
=
actionCollection
()
->
addAction
(
QStringLiteral
(
"file_save_all"
));
a
->
setIcon
(
QIcon
::
fromTheme
(
QStringLiteral
(
"document-save-all"
)));
...
...
@@ -1491,3 +1494,57 @@ void KateMainWindow::addRecentOpenedFile(const QUrl &url)
// to the global "Recent Document Menu", see bug 420504
// KRecentDocument::add(url);
}
void
KateMainWindow
::
hideWelcomeView
()
{
if
(
auto
welcomeView
=
qobject_cast
<
WelcomeView
*>
((
viewManager
()
->
activeViewSpace
())
->
currentWidget
()))
{
QTimer
::
singleShot
(
0
,
welcomeView
,
[
this
,
welcomeView
]()
{
removeWidget
(
welcomeView
);
});
}
}
void
KateMainWindow
::
showWelcomeView
()
{
// delay the creation, e.g. used on startup
QTimer
::
singleShot
(
0
,
this
,
[
this
]()
{
if
(
activeView
())
return
;
auto
vs
=
viewManager
()
->
activeViewSpace
();
if
(
vs
)
{
m_welcomeView
=
new
WelcomeView
(
this
);
// todo m_welcomeView->installEventFilter(this);
connect
(
m_welcomeView
,
&
WelcomeView
::
openClicked
,
this
,
[
this
]()
{
viewManager
()
->
slotDocumentOpen
();
});
connect
(
m_welcomeView
,
&
WelcomeView
::
recentItemClicked
,
this
,
[
this
](
const
QUrl
&
url
)
{
openUrl
(
url
);
});
connect
(
m_welcomeView
,
&
WelcomeView
::
forgetRecentItem
,
this
,
&
KateMainWindow
::
forgetRecentItem
);
addWidget
(
m_welcomeView
);
refreshRecentsOnWelcomeView
();
}
});
}
void
KateMainWindow
::
refreshRecentsOnWelcomeView
()
{
saveRecents
();
m_welcomeView
->
loadRecents
();
}
void
KateMainWindow
::
forgetRecentItem
(
QUrl
const
&
url
)
{
if
(
m_fileOpenRecent
!=
nullptr
)
{
m_fileOpenRecent
->
removeUrl
(
url
);
saveRecents
();
refreshRecentsOnWelcomeView
();
}
}
void
KateMainWindow
::
saveRecents
()
{
m_fileOpenRecent
->
saveEntries
(
KSharedConfig
::
openConfig
()
->
group
(
"Recent Files"
));
}
apps/lib/katemainwindow.h
View file @
2cda9f65
...
...
@@ -44,6 +44,7 @@ class KRecentFilesAction;
class
KateOutputView
;
class
KateViewManager
;
class
KateMwModOnHdDialog
;
class
WelcomeView
;
// Helper layout class to always provide minimum size
class
KateContainerStackedLayout
:
public
QStackedLayout
...
...
@@ -303,6 +304,9 @@ public:
*/
void
addRecentOpenedFile
(
const
QUrl
&
url
);
// TODO
void
saveRecents
();
//
// KTextEditor::MainWindow interface, get called by invokeMethod from our wrapper object!
//
...
...
@@ -558,6 +562,13 @@ public Q_SLOTS:
*/
void
showMessage
(
const
QVariantMap
&
map
);
// TODO
public
Q_SLOTS
:
void
hideWelcomeView
();
void
showWelcomeView
();
void
refreshRecentsOnWelcomeView
();
void
forgetRecentItem
(
QUrl
const
&
url
);
private
Q_SLOTS
:
void
slotUpdateBottomViewBar
();
...
...
@@ -672,6 +683,8 @@ private:
*/
KateOutputView
*
m_outputView
=
nullptr
;
WelcomeView
*
m_welcomeView
=
nullptr
;
public:
/**
* The available actions for the mouse back button, used as indexing
...
...
apps/lib/kateviewmanager.cpp
View file @
2cda9f65
...
...
@@ -13,7 +13,7 @@
#include
"katemainwindow.h"
#include
"kateupdatedisabler.h"
#include
"kateviewspace.h"
#include
"
kate
welcomeview.h"
#include
"welcomeview.h"
#include
<KTextEditor/Attribute>
#include
<KTextEditor/Document>
...
...
@@ -75,7 +75,7 @@ KateViewManager::KateViewManager(QWidget *parentW, KateMainWindow *parent)
connect
(
KateApp
::
self
()
->
documentManager
(),
&
KateDocManager
::
documentsDeleted
,
this
,
&
KateViewManager
::
documentsDeleted
);
// ensure we have the welcome view if no active view is there
showWelcomeView
IfNeeded
();
mainWindow
()
->
showWelcomeView
();
}
KateViewManager
::~
KateViewManager
()
...
...
@@ -497,12 +497,7 @@ KTextEditor::View *KateViewManager::createView(KTextEditor::Document *doc, KateV
/**
* ensure the initial welcome view vanishes as soon as we have some real view!
*/
if
(
auto
welcomeView
=
qobject_cast
<
KateWelcomeView
*>
((
vs
?
vs
:
activeViewSpace
())
->
currentWidget
()))
{
// delay the deletion, we might be in event handling of some action from the welcome view itself!
QTimer
::
singleShot
(
0
,
welcomeView
,
[
this
,
welcomeView
]()
{
mainWindow
()
->
removeWidget
(
welcomeView
);
});
}
mainWindow
()
->
hideWelcomeView
();
/**
* create view, registers its XML gui itself
...
...
@@ -1098,7 +1093,7 @@ void KateViewManager::onViewSpaceEmptied(KateViewSpace *vs)
}
// else we want to trigger showing of the welcome view
showWelcomeView
IfNeeded
();
mainWindow
()
->
showWelcomeView
();
}
void
KateViewManager
::
setShowUrlNavBar
(
bool
show
)
...
...
@@ -1512,13 +1507,3 @@ void KateViewManager::moveSplitter(Qt::Key key, int repeats)
currentSplitter
=
qobject_cast
<
KateSplitter
*>
(
currentSplitter
->
parentWidget
());
}
}
void
KateViewManager
::
showWelcomeViewIfNeeded
()
{
// delay the creation, e.g. used on startup
QTimer
::
singleShot
(
0
,
this
,
[
this
]()
{
if
(
activeView
())
return
;
mainWindow
()
->
addWidget
(
new
KateWelcomeView
());
});
}
apps/lib/kateviewmanager.h
View file @
2cda9f65
...
...
@@ -309,12 +309,6 @@ public Q_SLOTS:
void
setShowUrlNavBar
(
bool
show
);
bool
showUrlNavBar
()
const
;
/**
* Trigger creation of welcome view via timer.
* Will do nothing if we have some view around when the timer triggers.
*/
void
showWelcomeViewIfNeeded
();
private:
KateMainWindow
*
m_mainWindow
;
...
...
apps/lib/recentitemsmodel.cpp
0 → 100644
View file @
2cda9f65
/*
SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
"recentitemsmodel.h"
#include
"kateconfigdialog.h"
#include
<QFile>
#include
<QFileIconProvider>
#include
<QFileInfo>
#include
<QIcon>
#include
<KConfigGroup>
RecentItemsModel
::
RecentItemsModel
()
{
m_maxItems
=
KateConfigDialog
::
recentFilesMaxCount
();
}
RecentItemsModel
::~
RecentItemsModel
()
{
}
void
RecentItemsModel
::
loadEntries
(
const
KConfigGroup
&
cg
)
{
clearEntries
();
// Based on implementation of KRecentFilesAction::loadEntries.
QString
key
;
QString
value
;
QString
nameKey
;
QString
nameValue
;
QUrl
url
;
// read file list
for
(
int
i
=
1
;
i
<=
maxItems
();
i
++
)
{
key
=
QStringLiteral
(
"File%1"
).
arg
(
i
);
value
=
cg
.
readPathEntry
(
key
,
QString
());
if
(
value
.
isEmpty
())
{
continue
;
}
url
=
QUrl
::
fromUserInput
(
value
);
// Don't restore if file doesn't exist anymore
if
(
url
.
isLocalFile
()
&&
!
QFile
::
exists
(
url
.
toLocalFile
()))
{
continue
;
}
nameKey
=
QStringLiteral
(
"Name%1"
).
arg
(
i
);
nameValue
=
cg
.
readPathEntry
(
nameKey
,
url
.
fileName
());
m_recentItems
.
append
(
RecentItem
{.
name
=
nameValue
,
.
url
=
url
});
}
Q_EMIT
layoutChanged
();
}
void
RecentItemsModel
::
clearEntries
()
{
m_recentItems
.
clear
();
Q_EMIT
layoutChanged
();
}
int
RecentItemsModel
::
rowCount
(
const
QModelIndex
&
parent
)
const
{
Q_UNUSED
(
parent
);
return
m_recentItems
.
size
();
}
QVariant
RecentItemsModel
::
data
(
const
QModelIndex
&
index
,
int
role
)
const
{
const
RecentItemsModel
::
RecentItem
*
item
=
getItem
(
index
);
if
(
item
!=
nullptr
)
{
switch
(
role
)
{
case
Qt
::
ItemDataRole
::
DisplayRole
:
if
(
item
->
name
.
isEmpty
())
{
if
(
item
->
url
.
isLocalFile
())
{
return
item
->
url
.
toLocalFile
();
}
else
{
return
item
->
url
.
toString
();
}
}
else
{
return
item
->
name
;
}
case
Qt
::
ItemDataRole
::
ToolTipRole
:
if
(
item
->
url
.
isLocalFile
())
{
return
item
->
url
.
toLocalFile
();
}
else
{
return
item
->
url
.
toString
();
}
case
Qt
::
ItemDataRole
::
DecorationRole
:
if
(
item
->
url
.
isLocalFile
())
{
return
m_iconProvider
.
icon
(
QFileInfo
(
item
->
url
.
toLocalFile
()));
}
else
{
// Fallback icon for remote files.
return
QIcon
::
fromTheme
(
QStringLiteral
(
"network-server"
));
}
default:
return
QVariant
();
}
}
else
{
return
QVariant
();
}
}
RecentItemsModel
::
RecentItem
const
*
RecentItemsModel
::
getItem
(
int
index
)
const
{
if
(
m_recentItems
.
size
()
>
index
&&
index
>=
0
)
{
// We reverse the order of items.
return
&
m_recentItems
[
m_recentItems
.
size
()
-
index
-
1
];
}
else
{
return
nullptr
;
}
}
RecentItemsModel
::
RecentItem
const
*
RecentItemsModel
::
getItem
(
const
QModelIndex
&
index
)
const
{
return
getItem
(
index
.
row
());
}
\ No newline at end of file
apps/lib/recentitemsmodel.h
0 → 100644
View file @
2cda9f65
/*
SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef RECENTITEMSMODEL_H
#define RECENTITEMSMODEL_H
#include
<QAbstractListModel>
#include
<QFileIconProvider>
#include
<QList>
#include
<QModelIndex>
#include
<QString>
#include
<QUrl>
class
KConfigGroup
;
/**
* @todo write docs
*/
class
RecentItemsModel
:
public
QAbstractListModel
{
Q_OBJECT
public:
struct
RecentItem
{
QString
name
;
QUrl
url
;
};
/**
* Default constructor
*/
RecentItemsModel
();
/**
* Destructor
*/
~
RecentItemsModel
()
override
;
void
loadEntries
(
const
KConfigGroup
&
cg
);
void
clearEntries
();
int
maxItems
()
const
{
return
m_maxItems
;
}
RecentItemsModel
::
RecentItem
const
*
getItem
(
const
QModelIndex
&
)
const
;
RecentItemsModel
::
RecentItem
const
*
getItem
(
int
index
)
const
;
// Model implementation:
int
rowCount
(
const
QModelIndex
&
parent
=
QModelIndex
())
const
override
;
QVariant
data
(
const
QModelIndex
&
index
,
int
role
=
Qt
::
ItemDataRole
::
DisplayRole
)
const
override
;
private:
QList
<
RecentItemsModel
::
RecentItem
>
m_recentItems
;
int
m_maxItems
;
QFileIconProvider
m_iconProvider
;
};
#endif // RECENTITEMSMODEL_H
\ No newline at end of file
apps/lib/welcomeview.cpp
0 → 100644
View file @
2cda9f65
/*
SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
"welcomeview.h"
#include
<KConfigGroup>
#include
<KIconLoader>
#include
<KSharedConfig>
#include
<QAction>
#include
<QClipboard>
#include
<QDesktopServices>
#include
<QDir>
#include
<QGraphicsOpacityEffect>
#include
<QGuiApplication>
#include
<QMenu>
#include
<QResizeEvent>
#include
<QStyledItemDelegate>
#include
<QVBoxLayout>
#include
<klocalizedstring.h>
#include
"kateviewspace.h"
#include
"recentitemsmodel.h"
class
RecentsListItemDelegate
:
public
QStyledItemDelegate
{
Q_OBJECT
public:
explicit
RecentsListItemDelegate
(
WelcomeView
*
welcomeView
)
:
m_welcomeView
(
welcomeView
)
{
}
WelcomeView
*
welcomeView
()
const
{
return
m_welcomeView
;
}
bool
editorEvent
(
QEvent
*
event
,
QAbstractItemModel
*
aModel
,
const
QStyleOptionViewItem
&
styleOptionViewItem
,
const
QModelIndex
&
index
)
override
{
const
RecentItemsModel
*
model
=
static_cast
<
RecentItemsModel
*>
(
aModel
);
const
RecentItemsModel
::
RecentItem
*
item
=
model
->
getItem
(
index
);
bool
willOpenMenu
=
false
;
QPoint
menuPosition
;
if
(
item
!=
nullptr
)
{
if
(
event
->
type
()
==
QEvent
::
ContextMenu
)
{
willOpenMenu
=
true
;
menuPosition
=
static_cast
<
QContextMenuEvent
*>
(
event
)
->
globalPos
();
}
if
(
event
->
type
()
==
QEvent
::
MouseButtonPress
)
{
if
(
static_cast
<
QMouseEvent
*>
(
event
)
->
button
()
==
Qt
::
MouseButton
::
RightButton
)
{
willOpenMenu
=
true
;
menuPosition
=
static_cast
<
QMouseEvent
*>
(
event
)
->
globalPos
();
}
}
if
(
willOpenMenu
)
{
event
->
accept
();
QMenu
menu
;
QAction
*
copyPathAction
=
new
QAction
(
i18n
(
"&Copy Path"
));
copyPathAction
->
setIcon
(
QIcon
::
fromTheme
(
QStringLiteral
(
"edit-copy"
)));
connect
(
copyPathAction
,
&
QAction
::
triggered
,
this
,
[
item
]()
{
QString
path
;
if
(
item
->
url
.
isLocalFile
())
{
path
=
item
->
url
.
toLocalFile
();
}
else
{
path
=
item
->
url
.
toString
();
}
QGuiApplication
::
clipboard
()
->
setText
(
path
);
});
menu
.
addAction
(
copyPathAction
);
QAction
*
showDirectoryAction
=
new
QAction
(
i18n
(
"&Open Containing Folder"
));
showDirectoryAction
->
setIcon
(
QIcon
::
fromTheme
(
QStringLiteral
(
"document-open-folder"
)));
connect
(
showDirectoryAction
,
&
QAction
::
triggered
,
this
,
[
item
]()
{
if
(
item
->
url
.
isLocalFile
())
{
QFileInfo
fileInfo
(
item
->
url
.
toLocalFile
());
QDir
parentDir
=
fileInfo
.
dir
();
QUrl
parentDirUrl
=
QUrl
::
fromLocalFile
(
parentDir
.
absolutePath
());
QDesktopServices
::
openUrl
(
parentDirUrl
);
}
});
menu
.
addAction
(
showDirectoryAction
);
if
(
!
item
->
url
.
isLocalFile
())
{
showDirectoryAction
->
setEnabled
(
false
);
}
QAction
*
forgetItemAction
=
new
QAction
(
i18nc
(
"recent items context menu"
,
"&Forget This Item"
));
forgetItemAction
->
setIcon
(
QIcon
::
fromTheme
(
QStringLiteral
(
"edit-clear-history"
)));
connect
(
forgetItemAction
,
&
QAction
::
triggered
,
this
,
[
this
,
item
]()
{
Q_EMIT
welcomeView
()
->
forgetRecentItem
(
item
->
url
);
});
menu
.
addAction
(
forgetItemAction
);
menu
.
exec
(
menuPosition
);
return
true
;
}
}
return
QStyledItemDelegate
::
editorEvent
(
event
,
aModel
,
styleOptionViewItem
,
index
);
}
private:
WelcomeView
*
m_welcomeView
;
};
WelcomeView
::
WelcomeView
(
QWidget
*
parent
)
:
QWidget
(
parent
)
,
m_recentsModel
(
new
RecentItemsModel
)
,
m_recentsItemDelegate
(
new
RecentsListItemDelegate
(
this
))
{
Q_ASSERT
(
parent
);
setupUi
(
this
);
setWindowTitle
(
i18n
(
"Welcome"
));
KIconLoader
loader
;
appIcon
->
setPixmap
(
loader
.
loadIcon
(
QStringLiteral
(
"kate"
),
KIconLoader
::
Group
::
Desktop
,
KIconLoader
::
SizeEnormous
));
connect
(
openButton
,
&
QPushButton
::
clicked
,
this
,
&
WelcomeView
::
openClicked
);
recentsListView
->
setContextMenuPolicy
(
Qt
::
DefaultContextMenu
);
recentsListView
->
setModel
(
m_recentsModel
);
recentsListView
->
setItemDelegate
(
m_recentsItemDelegate
);
connect
(
recentsListView
,
&
QListView
::
activated
,
this
,
&
WelcomeView
::
recentsItemActivated
);
connect
(
m_recentsModel
,
&
RecentItemsModel
::
layoutChanged
,
this
,
&
WelcomeView
::
recentListChanged
);
QVBoxLayout
*
noRecentsLayout
=
new
QVBoxLayout
(
recentsListView
);
recentsListView
->
setLayout
(
noRecentsLayout
);
m_noRecentsLabel
=
new
QLabel
(
recentsListView
);
QFont
placeholderLabelFont
;
// To match the size of a level 2 Heading/KTitleWidget
placeholderLabelFont
.
setPointSize
(
qRound
(
placeholderLabelFont
.
pointSize
()
*
1.3
));
noRecentsLayout
->
addWidget
(
m_noRecentsLabel
);
m_noRecentsLabel
->
setFont
(
placeholderLabelFont
);
m_noRecentsLabel
->
setTextInteractionFlags
(
Qt
::
NoTextInteraction
);
m_noRecentsLabel
->
setWordWrap
(
true
);
m_noRecentsLabel
->
setAlignment
(
Qt
::
AlignCenter
);
m_noRecentsLabel
->
setText
(
i18nc
(
"on welcome screen"
,
"No recent documents"
));
// Match opacity of QML placeholder label component
auto
*
effect
=
new
QGraphicsOpacityEffect
(
m_noRecentsLabel
);
effect
->
setOpacity
(
0.5
);
m_noRecentsLabel
->
setGraphicsEffect
(
effect
);
connect
(
forgetAllButton
,
&
QToolButton
::
clicked
,
this
,
&
WelcomeView
::
forgetAllRecents
);
}
WelcomeView
::~
WelcomeView
()
{
delete
m_recentsModel
;
delete
m_recentsItemDelegate
;
}
void
WelcomeView
::
loadRecents
()
{
m_recentsModel
->
loadEntries
(
KSharedConfig
::
openConfig
()
->
group
(
"Recent Files"
));
}
int
WelcomeView
::
recentsCount
()
{
return
m_recentsModel
->
rowCount
();
}
void
WelcomeView
::
recentsItemActivated
(
const
QModelIndex
&
index
)
{
const
RecentItemsModel
::
RecentItem
*
item
=
m_recentsModel
->
getItem
(
index
);
if
(
item
!=
nullptr
)
{
Q_EMIT
recentItemClicked
(
item
->
url
);
}
}
void
WelcomeView
::
recentListChanged
()
{
if
(
recentsCount
()
==
0
)
{
m_noRecentsLabel
->
show
();
forgetAllButton
->
setEnabled
(
false
);
}
else
{
m_noRecentsLabel
->
hide
();
forgetAllButton
->
setEnabled
(
true
);
}
}
#include
"welcomeview.moc"
apps/lib/welcomeview.h
0 → 100644
View file @
2cda9f65
/*
SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef WELCOMEVIEW_H
#define WELCOMEVIEW_H
#include
"ui_welcomeview.h"
#include
<QFrame>
#include
<QUrl>
class
QListWidgetItem
;
class
QLabel
;
class
KRecentFilesAction
;
class
KateViewSpace
;
class
RecentItemsModel
;
class
RecentsListItemDelegate
;