@ -30,6 +30,7 @@
# include <QLayout>
# include <QLayout>
# include <QDebug>
# include <QDebug>
# include <QTimer>
# include <QTimer>
# include <QTime>
# include <QSettings>
# include <QSettings>
# include <QStringBuilder>
# include <QStringBuilder>
# include <QDir>
# include <QDir>
@ -37,19 +38,19 @@
# include <QDropEvent>
# include <QDropEvent>
# include <QMimeData>
# include <QMimeData>
# include <QPaintEvent>
# include <QPaintEvent>
# include <QStandardPaths>
# include "./application.h"
# include "./application.h"
# include "mainwindow.h"
# include "mainwindow.h"
# include "desktopitemdelegate.h"
# include <libfm-qt/foldermenu.h>
# include <libfm-qt/foldermenu.h>
# include <libfm-qt/filemenu.h>
# include <libfm-qt/filemenu.h>
# include <libfm-qt/folderitemdelegate.h>
# include <libfm-qt/cachedfoldermodel.h>
# include <libfm-qt/cachedfoldermodel.h>
# include <libfm-qt/folderview_p.h>
# include <libfm-qt/folderview_p.h>
# include <libfm-qt/fileoperation.h>
# include <libfm-qt/fileoperation.h>
# include <libfm-qt/filepropsdialog.h>
# include <libfm-qt/filepropsdialog.h>
# include <libfm-qt/utilities.h>
# include <libfm-qt/utilities.h>
# include <libfm-qt/path.h>
# include <libfm-qt/core/fileinfo.h>
# include <libfm-qt/fileinfo.h>
# include "xdgdir.h"
# include "xdgdir.h"
# include <QX11Info>
# include <QX11Info>
@ -57,17 +58,23 @@
# include <xcb/xcb.h>
# include <xcb/xcb.h>
# include <X11/Xlib.h>
# include <X11/Xlib.h>
# define MIN_SLIDE_INTERVAL 5*60000 // 5 min
# define MAX_SLIDE_INTERVAL (24*60+55)*60000 // 24 h and 55 min
namespace PCManFM {
namespace PCManFM {
DesktopWindow : : DesktopWindow ( int screenNum ) :
DesktopWindow : : DesktopWindow ( int screenNum ) :
View ( Fm : : FolderView : : IconMode ) ,
View ( Fm : : FolderView : : IconMode ) ,
proxyModel_ ( NULL ) ,
proxyModel_ ( nullptr ) ,
model_ ( NULL ) ,
model_ ( nullptr ) ,
wallpaperMode_ ( WallpaperNone ) ,
wallpaperMode_ ( WallpaperNone ) ,
fileLauncher_ ( NULL ) ,
slideShowInterval_ ( 0 ) ,
wallpaperTimer_ ( nullptr ) ,
wallpaperRandomize_ ( false ) ,
fileLauncher_ ( nullptr ) ,
showWmMenu_ ( false ) ,
showWmMenu_ ( false ) ,
screenNum_ ( screenNum ) ,
screenNum_ ( screenNum ) ,
relayoutTimer_ ( NULL ) {
relayoutTimer_ ( nullptr ) {
QDesktopWidget * desktopWidget = QApplication : : desktop ( ) ;
QDesktopWidget * desktopWidget = QApplication : : desktop ( ) ;
setWindowFlags ( Qt : : Window | Qt : : FramelessWindowHint ) ;
setWindowFlags ( Qt : : Window | Qt : : FramelessWindowHint ) ;
@ -84,9 +91,9 @@ DesktopWindow::DesktopWindow(int screenNum):
// This is to workaround Qt bug 54384 which affects Qt >= 5.6
// This is to workaround Qt bug 54384 which affects Qt >= 5.6
// https://bugreports.qt.io/browse/QTBUG-54384
// https://bugreports.qt.io/browse/QTBUG-54384
// Setting a QPixmap larger then the screen resolution to the background of a list view won't work.
// Setting a QPixmap larger then the screen resolution to desktop's QPalette won't work.
// So we did a hack here: Disable the automatic background painting .
// So we make the viewport transparent by preventing its backround from being filled automatically .
// Then paint the background of the list view ourselves by hook into its paint event handling method with a event filter .
// Then we paint desktop's background ourselves by using its paint event handling method .
listView_ - > viewport ( ) - > setAutoFillBackground ( false ) ;
listView_ - > viewport ( ) - > setAutoFillBackground ( false ) ;
// NOTE: When XRnadR is in use, the all screens are actually combined to form a
// NOTE: When XRnadR is in use, the all screens are actually combined to form a
@ -98,7 +105,8 @@ DesktopWindow::DesktopWindow(int screenNum):
loadItemPositions ( ) ;
loadItemPositions ( ) ;
Settings & settings = static_cast < Application * > ( qApp ) - > settings ( ) ;
Settings & settings = static_cast < Application * > ( qApp ) - > settings ( ) ;
model_ = Fm : : CachedFolderModel : : modelFromPath ( Fm : : Path : : getDesktop ( ) ) ;
auto desktopPath = Fm : : FilePath : : fromLocalPath ( XdgDir : : readDesktopDir ( ) . toStdString ( ) . c_str ( ) ) ;
model_ = Fm : : CachedFolderModel : : modelFromPath ( desktopPath ) ;
folder_ = model_ - > folder ( ) ;
folder_ = model_ - > folder ( ) ;
proxyModel_ = new Fm : : ProxyFolderModel ( ) ;
proxyModel_ = new Fm : : ProxyFolderModel ( ) ;
@ -116,10 +124,6 @@ DesktopWindow::DesktopWindow(int screenNum):
connect ( listView_ , & QListView : : indexesMoved , this , & DesktopWindow : : onIndexesMoved ) ;
connect ( listView_ , & QListView : : indexesMoved , this , & DesktopWindow : : onIndexesMoved ) ;
}
}
// set our own delegate
delegate_ = new DesktopItemDelegate ( listView_ ) ;
listView_ - > setItemDelegateForColumn ( Fm : : FolderModel : : ColumnFileName , delegate_ ) ;
// remove frame
// remove frame
listView_ - > setFrameShape ( QFrame : : NoFrame ) ;
listView_ - > setFrameShape ( QFrame : : NoFrame ) ;
// inhibit scrollbars FIXME: this should be optional in the future
// inhibit scrollbars FIXME: this should be optional in the future
@ -143,7 +147,7 @@ DesktopWindow::DesktopWindow(int screenNum):
connect ( shortcut , & QShortcut : : activated , this , & DesktopWindow : : onPasteActivated ) ;
connect ( shortcut , & QShortcut : : activated , this , & DesktopWindow : : onPasteActivated ) ;
shortcut = new QShortcut ( QKeySequence ( Qt : : CTRL + Qt : : Key_A ) , this ) ; // select all
shortcut = new QShortcut ( QKeySequence ( Qt : : CTRL + Qt : : Key_A ) , this ) ; // select all
connect ( shortcut , & QShortcut : : activated , listView_ , & QList View: : selectAll ) ;
connect ( shortcut , & QShortcut : : activated , this , & Folder View: : selectAll ) ;
shortcut = new QShortcut ( QKeySequence ( Qt : : Key_Delete ) , this ) ; // delete
shortcut = new QShortcut ( QKeySequence ( Qt : : Key_Delete ) , this ) ; // delete
connect ( shortcut , & QShortcut : : activated , this , & DesktopWindow : : onDeleteActivated ) ;
connect ( shortcut , & QShortcut : : activated , this , & DesktopWindow : : onDeleteActivated ) ;
@ -162,15 +166,24 @@ DesktopWindow::~DesktopWindow() {
listView_ - > viewport ( ) - > removeEventFilter ( this ) ;
listView_ - > viewport ( ) - > removeEventFilter ( this ) ;
listView_ - > removeEventFilter ( this ) ;
listView_ - > removeEventFilter ( this ) ;
if ( relayoutTimer_ )
if ( relayoutTimer_ ) {
relayoutTimer_ - > stop ( ) ;
delete relayoutTimer_ ;
delete relayoutTimer_ ;
}
if ( wallpaperTimer_ ) {
wallpaperTimer_ - > stop ( ) ;
delete wallpaperTimer_ ;
}
if ( proxyModel_ )
if ( proxyModel_ ) {
delete proxyModel_ ;
delete proxyModel_ ;
}
if ( model_ )
if ( model_ ) {
model_ - > unref ( ) ;
model_ - > unref ( ) ;
}
}
}
void DesktopWindow : : setBackground ( const QColor & color ) {
void DesktopWindow : : setBackground ( const QColor & color ) {
bgColor_ = color ;
bgColor_ = color ;
@ -185,10 +198,12 @@ void DesktopWindow::setForeground(const QColor& color) {
void DesktopWindow : : setShadow ( const QColor & color ) {
void DesktopWindow : : setShadow ( const QColor & color ) {
shadowColor_ = color ;
shadowColor_ = color ;
delegate_ - > setShadowColor ( color ) ;
auto delegate = static_cast < Fm : : FolderItemDelegate * > ( listView_ - > itemDelegateForColumn ( Fm : : FolderModel : : ColumnFileName ) ) ;
delegate - > setShadowColor ( color ) ;
}
}
void DesktopWindow : : onOpenDirRequested ( FmPath * path , int target ) {
void DesktopWindow : : onOpenDirRequested ( const Fm : : FilePath & path , int target ) {
Q_UNUSED ( target ) ;
// open in new window unconditionally.
// open in new window unconditionally.
Application * app = static_cast < Application * > ( qApp ) ;
Application * app = static_cast < Application * > ( qApp ) ;
MainWindow * newWin = new MainWindow ( path ) ;
MainWindow * newWin = new MainWindow ( path ) ;
@ -209,7 +224,7 @@ void DesktopWindow::resizeEvent(QResizeEvent* event) {
}
}
void DesktopWindow : : setDesktopFolder ( ) {
void DesktopWindow : : setDesktopFolder ( ) {
Fm : : Path path = Fm : : Path : : newFor Path( XdgDir : : readDesktopDir ( ) . toStdString ( ) . c_str ( ) ) ;
auto path = Fm : : FilePath : : fromLocal Path( XdgDir : : readDesktopDir ( ) . toStdString ( ) . c_str ( ) ) ;
model_ = Fm : : CachedFolderModel : : modelFromPath ( path ) ;
model_ = Fm : : CachedFolderModel : : modelFromPath ( path ) ;
proxyModel_ - > setSourceModel ( model_ ) ;
proxyModel_ - > setSourceModel ( model_ ) ;
}
}
@ -222,6 +237,22 @@ void DesktopWindow::setWallpaperMode(WallpaperMode mode) {
wallpaperMode_ = mode ;
wallpaperMode_ = mode ;
}
}
void DesktopWindow : : setLastSlide ( QString filename ) {
lastSlide_ = filename ;
}
void DesktopWindow : : setWallpaperDir ( QString dirname ) {
wallpaperDir_ = dirname ;
}
void DesktopWindow : : setSlideShowInterval ( int interval ) {
slideShowInterval_ = interval ;
}
void DesktopWindow : : setWallpaperRandomize ( bool randomize ) {
wallpaperRandomize_ = randomize ;
}
QImage DesktopWindow : : loadWallpaperFile ( QSize requiredSize ) {
QImage DesktopWindow : : loadWallpaperFile ( QSize requiredSize ) {
// NOTE: for ease of programming, we only use the cache for the primary screen.
// NOTE: for ease of programming, we only use the cache for the primary screen.
bool useCache = ( screenNum_ = = - 1 | | screenNum_ = = 0 ) ;
bool useCache = ( screenNum_ = = - 1 | | screenNum_ = = 0 ) ;
@ -230,8 +261,9 @@ QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) {
if ( useCache ) {
if ( useCache ) {
// see if we have a scaled version cached on disk
// see if we have a scaled version cached on disk
cacheFileName = QString : : fromLocal8Bit ( qgetenv ( " XDG_CACHE_HOME " ) ) ;
cacheFileName = QString : : fromLocal8Bit ( qgetenv ( " XDG_CACHE_HOME " ) ) ;
if ( cacheFileName . isEmpty ( ) )
if ( cacheFileName . isEmpty ( ) ) {
cacheFileName = QDir : : homePath ( ) % QLatin1String ( " /.cache " ) ;
cacheFileName = QDir : : homePath ( ) % QLatin1String ( " /.cache " ) ;
}
Application * app = static_cast < Application * > ( qApp ) ;
Application * app = static_cast < Application * > ( qApp ) ;
cacheFileName + = QLatin1String ( " /pcmanfm-qt/ " ) % app - > profileName ( ) ;
cacheFileName + = QLatin1String ( " /pcmanfm-qt/ " ) % app - > profileName ( ) ;
QDir ( ) . mkpath ( cacheFileName ) ; // ensure that the cache dir exists
QDir ( ) . mkpath ( cacheFileName ) ; // ensure that the cache dir exists
@ -254,20 +286,22 @@ QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) {
if ( cachedSize = = requiredSize ) { // see if the cached wallpaper has the size we want
if ( cachedSize = = requiredSize ) { // see if the cached wallpaper has the size we want
QImage image = reader . read ( ) ; // return the loaded image
QImage image = reader . read ( ) ; // return the loaded image
qDebug ( ) < < " origin " < < origin ;
qDebug ( ) < < " origin " < < origin ;
if ( origin = = wallpaperFile_ )
if ( origin = = wallpaperFile_ ) {
return image ;
return image ;
}
}
}
}
}
}
}
}
}
qDebug ( ) < < " no cached wallpaper. generate a new one! " ;
qDebug ( ) < < " no cached wallpaper. generate a new one! " ;
}
}
// we don't have a cached scaled image, load the original file
// we don't have a cached scaled image, load the original file
QImage image ( wallpaperFile_ ) ;
QImage image ( wallpaperFile_ ) ;
qDebug ( ) < < " size of original image " < < image . size ( ) ;
qDebug ( ) < < " size of original image " < < image . size ( ) ;
if ( image . isNull ( ) | | image . size ( ) = = requiredSize ) // if the original size is what we want
if ( image . isNull ( ) | | image . size ( ) = = requiredSize ) { // if the original size is what we want
return image ;
return image ;
}
// scale the original image
// scale the original image
QImage scaled = image . scaled ( requiredSize . width ( ) , requiredSize . height ( ) , Qt : : IgnoreAspectRatio , Qt : : SmoothTransformation ) ;
QImage scaled = image . scaled ( requiredSize . width ( ) , requiredSize . height ( ) , Qt : : IgnoreAspectRatio , Qt : : SmoothTransformation ) ;
@ -281,10 +315,12 @@ QImage DesktopWindow::loadWallpaperFile(QSize requiredSize) {
// write the scaled cache image to disk
// write the scaled cache image to disk
const char * format ; // we keep jpg format for *.jpg files, and use png format for others.
const char * format ; // we keep jpg format for *.jpg files, and use png format for others.
if ( wallpaperFile_ . endsWith ( QLatin1String ( " .jpg " ) , Qt : : CaseInsensitive ) | | wallpaperFile_ . endsWith ( QLatin1String ( " .jpeg " ) , Qt : : CaseInsensitive ) )
if ( wallpaperFile_ . endsWith ( QLatin1String ( " .jpg " ) , Qt : : CaseInsensitive ) | | wallpaperFile_ . endsWith ( QLatin1String ( " .jpeg " ) , Qt : : CaseInsensitive ) ) {
format = " JPG " ;
format = " JPG " ;
else
}
else {
format = " PNG " ;
format = " PNG " ;
}
scaled . save ( cacheFileName , format ) ;
scaled . save ( cacheFileName , format ) ;
}
}
qDebug ( ) < < " wallpaper cached saved to " < < cacheFileName ;
qDebug ( ) < < " wallpaper cached saved to " < < cacheFileName ;
@ -300,7 +336,16 @@ void DesktopWindow::updateWallpaper() {
QImage image ;
QImage image ;
if ( wallpaperMode_ = = WallpaperTile ) { // use the original size
if ( wallpaperMode_ = = WallpaperTile ) { // use the original size
image = QImage ( wallpaperFile_ ) ;
image = QImage ( wallpaperFile_ ) ;
pixmap = QPixmap : : fromImage ( image ) ;
// Note: We can't use the QPainter::drawTiledPixmap(), because it doesn't tile
// correctly for background pixmaps bigger than the current screen size.
const QSize s = size ( ) ;
pixmap = QPixmap { s } ;
QPainter painter { & pixmap } ;
for ( int x = 0 ; x < s . width ( ) ; x + = image . width ( ) ) {
for ( int y = 0 ; y < s . height ( ) ; y + = image . height ( ) ) {
painter . drawImage ( x , y , image ) ;
}
}
}
}
else if ( wallpaperMode_ = = WallpaperStretch ) {
else if ( wallpaperMode_ = = WallpaperStretch ) {
image = loadWallpaperFile ( size ( ) ) ;
image = loadWallpaperFile ( size ( ) ) ;
@ -333,10 +378,97 @@ void DesktopWindow::updateWallpaper() {
}
}
}
}
void DesktopWindow : : updateFromSettings ( Settings & settings ) {
bool DesktopWindow : : pickWallpaper ( ) {
if ( slideShowInterval_ < = 0
| | ! QFileInfo ( wallpaperDir_ ) . isDir ( ) ) {
return false ;
}
QList < QByteArray > formats = QImageReader : : supportedImageFormats ( ) ;
QStringList formatsFilters ;
for ( const QByteArray & format : formats )
formatsFilters < < QString ( " *. " ) + format ;
QDir folder ( wallpaperDir_ ) ;
QStringList files = folder . entryList ( formatsFilters ,
QDir : : Files | QDir : : NoDotAndDotDot ,
QDir : : Name ) ;
if ( ! files . isEmpty ( ) ) {
QString dir = wallpaperDir_ + QLatin1Char ( ' / ' ) ;
if ( ! wallpaperRandomize_ ) {
if ( ! lastSlide_ . startsWith ( dir ) ) { // not in the directory
wallpaperFile_ = dir + files . first ( ) ;
}
else {
QString ls = lastSlide_ . remove ( 0 , dir . size ( ) ) ;
if ( ls . isEmpty ( ) // invalid
| | ls . contains ( QLatin1Char ( ' / ' ) ) ) { // in a subdirectory or invalid
wallpaperFile_ = dir + files . first ( ) ;
}
else {
int index = files . indexOf ( ls ) ;
if ( index = = - 1 ) { // removed or invalid
wallpaperFile_ = dir + files . first ( ) ;
}
else {
wallpaperFile_ = dir + ( index + 1 < files . size ( )
? files . at ( index + 1 )
: files . first ( ) ) ;
}
}
}
}
else {
if ( files . size ( ) > 1 ) {
if ( lastSlide_ . startsWith ( dir ) ) {
QString ls = lastSlide_ . remove ( 0 , dir . size ( ) ) ;
if ( ! ls . isEmpty ( ) & & ! ls . contains ( QLatin1Char ( ' / ' ) ) )
files . removeOne ( ls ) ; // choose from other images
}
// this is needed for the randomness, especially when choosing the first wallpaper
qsrand ( ( uint ) QTime : : currentTime ( ) . msec ( ) ) ;
int randomValue = qrand ( ) % files . size ( ) ;
wallpaperFile_ = dir + files . at ( randomValue ) ;
}
else {
wallpaperFile_ = dir + files . first ( ) ;
}
}
if ( lastSlide_ ! = wallpaperFile_ ) {
lastSlide_ = wallpaperFile_ ;
Settings & settings = static_cast < Application * > ( qApp ) - > settings ( ) ;
settings . setLastSlide ( lastSlide_ ) ;
return true ;
}
}
return false ;
}
void DesktopWindow : : nextWallpaper ( ) {
if ( pickWallpaper ( ) ) {
updateWallpaper ( ) ;
update ( ) ;
}
}
void DesktopWindow : : updateFromSettings ( Settings & settings , bool changeSlide ) {
setDesktopFolder ( ) ;
setDesktopFolder ( ) ;
setWallpaperFile ( settings . wallpaper ( ) ) ;
setWallpaperFile ( settings . wallpaper ( ) ) ;
setWallpaperMode ( settings . wallpaperMode ( ) ) ;
setWallpaperMode ( settings . wallpaperMode ( ) ) ;
setLastSlide ( settings . lastSlide ( ) ) ;
QString wallpaperDir = settings . wallpaperDir ( ) ;
if ( wallpaperDir_ ! = wallpaperDir ) {
changeSlide = true ; // another wallpapaer directory; change slide!
}
setWallpaperDir ( wallpaperDir ) ;
int interval = settings . slideShowInterval ( ) ;
if ( interval > 0 & & ( interval < MIN_SLIDE_INTERVAL | | interval > MAX_SLIDE_INTERVAL ) ) {
interval = qBound ( MIN_SLIDE_INTERVAL , interval , MAX_SLIDE_INTERVAL ) ;
settings . setSlideShowInterval ( interval ) ;
}
setSlideShowInterval ( interval ) ;
setWallpaperRandomize ( settings . wallpaperRandomize ( ) ) ;
setFont ( settings . desktopFont ( ) ) ;
setFont ( settings . desktopFont ( ) ) ;
setIconSize ( Fm : : FolderView : : IconMode , QSize ( settings . desktopIconSize ( ) , settings . desktopIconSize ( ) ) ) ;
setIconSize ( Fm : : FolderView : : IconMode , QSize ( settings . desktopIconSize ( ) , settings . desktopIconSize ( ) ) ) ;
setMargins ( settings . desktopCellMargins ( ) ) ;
setMargins ( settings . desktopCellMargins ( ) ) ;
@ -346,13 +478,44 @@ void DesktopWindow::updateFromSettings(Settings& settings) {
setBackground ( settings . desktopBgColor ( ) ) ;
setBackground ( settings . desktopBgColor ( ) ) ;
setShadow ( settings . desktopShadowColor ( ) ) ;
setShadow ( settings . desktopShadowColor ( ) ) ;
showWmMenu_ = settings . showWmMenu ( ) ;
showWmMenu_ = settings . showWmMenu ( ) ;
if ( slideShowInterval_ > 0
& & QFileInfo ( wallpaperDir_ ) . isDir ( ) ) {
if ( ! wallpaperTimer_ ) {
changeSlide = true ; // slideshow activated; change slide!
wallpaperTimer_ = new QTimer ( ) ;
connect ( wallpaperTimer_ , & QTimer : : timeout , this , & DesktopWindow : : nextWallpaper ) ;
}
else {
wallpaperTimer_ - > stop ( ) ; // restart the timer after updating wallpaper
}
if ( changeSlide ) {
pickWallpaper ( ) ;
}
else if ( QFile : : exists ( lastSlide_ ) ) {
/* show the last slide if it still exists,
otherwise show the wallpaper until timeout */
wallpaperFile_ = lastSlide_ ;
}
}
else if ( wallpaperTimer_ ) {
wallpaperTimer_ - > stop ( ) ;
delete wallpaperTimer_ ;
wallpaperTimer_ = nullptr ;
}
updateWallpaper ( ) ;
updateWallpaper ( ) ;
update ( ) ;
update ( ) ;
if ( wallpaperTimer_ ) {
wallpaperTimer_ - > start ( slideShowInterval_ ) ;
}
}
}
void DesktopWindow : : onFileClicked ( int type , FmFileInfo * fileInfo ) {
void DesktopWindow : : onFileClicked ( int type , const std : : shared_ptr < const Fm : : FileInfo > & fileInfo ) {
if ( ! fileInfo & & showWmMenu_ )
if ( ! fileInfo & & showWmMenu_ ) {
return ; // do not show the popup if we want to use the desktop menu provided by the WM.
return ; // do not show the popup if we want to use the desktop menu provided by the WM.
}
View : : onFileClicked ( type , fileInfo ) ;
View : : onFileClicked ( type , fileInfo ) ;
}
}
@ -364,15 +527,15 @@ void DesktopWindow::prepareFileMenu(Fm::FileMenu* menu) {
menu - > insertSeparator ( menu - > separator2 ( ) ) ;
menu - > insertSeparator ( menu - > separator2 ( ) ) ;
menu - > insertAction ( menu - > separator2 ( ) , action ) ;
menu - > insertAction ( menu - > separator2 ( ) , action ) ;
Fm : : FileInfoList files = menu - > files ( ) ;
bool checked ( true ) ;
// select exactly one item
auto files = menu - > files ( ) ;
if ( fm_file_info_list_get_length ( files ) = = 1 ) {
for ( const auto & file : files ) {
Fm : : FileInfo file = menu - > firstFile ( ) ;
if ( customItemPos_ . find ( file - > name ( ) ) = = customItemPos_ . cend ( ) ) {
if ( customItemPos_ . find ( file . getName ( ) ) ! = customItemPos_ . end ( ) ) {
checked = false ;
// the file item has a custom position
break ;
action - > setChecked ( true ) ;
}
}
}
}
action - > setChecked ( checked ) ;
connect ( action , & QAction : : toggled , this , & DesktopWindow : : onStickToCurrentPos ) ;
connect ( action , & QAction : : toggled , this , & DesktopWindow : : onStickToCurrentPos ) ;
}
}
@ -390,31 +553,42 @@ void DesktopWindow::onDesktopPreferences() {
}
}
void DesktopWindow : : onRowsInserted ( const QModelIndex & parent , int start , int end ) {
void DesktopWindow : : onRowsInserted ( const QModelIndex & parent , int start , int end ) {
queueRelayout ( ) ;
Q_UNUSED ( parent ) ;
Q_UNUSED ( start ) ;
Q_UNUSED ( end ) ;
// disable view updates temporarily and delay relayout to prevent items from shaking
listView_ - > setUpdatesEnabled ( false ) ;
queueRelayout ( 100 ) ;
}
}
void DesktopWindow : : onRowsAboutToBeRemoved ( const QModelIndex & parent , int start , int end ) {
void DesktopWindow : : onRowsAboutToBeRemoved ( const QModelIndex & parent , int start , int end ) {
Q_UNUSED ( parent ) ;
Q_UNUSED ( parent ) ;
Q_UNUSED ( start ) ;
Q_UNUSED ( start ) ;
Q_UNUSED ( end ) ;
Q_UNUSED ( end ) ;
if ( ! customItemPos_ . isE mpty( ) ) {
if ( ! customItemPos_ . e mpty( ) ) {
// also delete stored custom item positions for the items currently being removed.
// also delete stored custom item positions for the items currently being removed.
// Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows
// Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows
// aren't removed yet, files are already removed.
// aren't removed yet, files are already removed.
QHash < QByteArray , QPoint > _customItemPos = customItemPos_ ;
bool changed = false ;
char * dektopPath = Fm : : Path : : getDesktop ( ) . toStr ( ) ;
char * dektopPath = Fm : : Path : : getDesktop ( ) . toStr ( ) ;
QString desktopDir = QString ( dektopPath ) + QString ( " / " ) ;
QString desktopDir = QString ( dektopPath ) + QString ( " / " ) ;
g_free ( dektopPath ) ;
g_free ( dektopPath ) ;
QHash < QByteArray , QPoint > : : iterator it ;
for ( auto it = customItemPos_ . cbegin ( ) ; it ! = customItemPos_ . cend ( ) ; ) {
for ( it = _customItemPos . begin ( ) ; it ! = _customItemPos . end ( ) ; + + it ) {
auto & name = it - > first ;
const QByteArray & name = it . key ( ) ;
if ( ! QFile : : exists ( desktopDir + QString : : fromStdString ( name ) ) ) {
if ( ! QFile : : exists ( desktopDir + QString : : fromUtf8 ( name , name . length ( ) ) ) )
it = customItemPos_ . erase ( it ) ;
customItemPos_ . remove ( it . key ( ) ) ;
changed = true ;
}
else {
+ + it ;
}
}
}
if ( customItemPos_ ! = _customItemPos )
if ( changed ) {
saveItemPositions ( ) ;
saveItemPositions ( ) ;
}
}
queueRelayout ( ) ;
}
listView_ - > setUpdatesEnabled ( false ) ;
queueRelayout ( 100 ) ;
}
}
void DesktopWindow : : onLayoutChanged ( ) {
void DesktopWindow : : onLayoutChanged ( ) {
@ -440,8 +614,8 @@ void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex&
for ( int i = topLeft . row ( ) ; i < = bottomRight . row ( ) ; + + i ) {
for ( int i = topLeft . row ( ) ; i < = bottomRight . row ( ) ; + + i ) {
QModelIndex index = topLeft . sibling ( i , 0 ) ;
QModelIndex index = topLeft . sibling ( i , 0 ) ;
if ( index . isValid ( ) & & displayNames_ . contains ( index ) ) {
if ( index . isValid ( ) & & displayNames_ . contains ( index ) ) {
Fm : : FileInf o file = proxyModel_ - > fileInfoFromIndex ( index ) ;
aut o file = proxyModel_ - > fileInfoFromIndex ( index ) ;
if ( displayNames_ [ index ] ! = file . getDisp Name( ) ) {
if ( displayNames_ [ index ] ! = file - > display Name( ) ) {
relayout = true ;
relayout = true ;
break ;
break ;
}
}
@ -456,6 +630,8 @@ void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex&
}
}
void DesktopWindow : : onIndexesMoved ( const QModelIndexList & indexes ) {
void DesktopWindow : : onIndexesMoved ( const QModelIndexList & indexes ) {
auto delegate = static_cast < Fm : : FolderItemDelegate * > ( listView_ - > itemDelegateForColumn ( 0 ) ) ;
auto itemSize = delegate - > itemSize ( ) ;
// remember the custom position for the items
// remember the custom position for the items
Q_FOREACH ( const QModelIndex & index , indexes ) {
Q_FOREACH ( const QModelIndex & index , indexes ) {
// Under some circumstances, Qt might emit indexMoved for
// Under some circumstances, Qt might emit indexMoved for
@ -464,17 +640,22 @@ void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) {
// Since we only care about rows, not individual cells,
// Since we only care about rows, not individual cells,
// let's handle column 0 of every row here.
// let's handle column 0 of every row here.
if ( index . column ( ) = = 0 ) {
if ( index . column ( ) = = 0 ) {
Fm : : FileInf o file = proxyModel_ - > fileInfoFromIndex ( index ) ;
aut o file = proxyModel_ - > fileInfoFromIndex ( index ) ;
QRect itemRect = listView_ - > rectForIndex ( index ) ;
QRect itemRect = listView_ - > rectForIndex ( index ) ;
QPoint tl = itemRect . topLeft ( ) ;
QPoint tl = itemRect . topLeft ( ) ;
QRect workArea = qApp - > desktop ( ) - > availableGeometry ( screenNum_ ) ;
QRect workArea = qApp - > desktop ( ) - > availableGeometry ( screenNum_ ) ;
workArea . adjust ( 12 , 12 , - 12 , - 12 ) ;
workArea . adjust ( 12 , 12 , - 12 , - 12 ) ;
if ( customItemPos_ . keys ( tl ) . isEmpty ( ) // don't put items on each other
// check if the position is occupied by another item
auto existingItem = std : : find_if ( customItemPos_ . cbegin ( ) , customItemPos_ . cend ( ) , [ tl ] ( const std : : pair < std : : string , QPoint > & elem ) {
return elem . second = = tl ;
} ) ;
if ( existingItem = = customItemPos_ . cend ( ) // don't put items on each other
& & tl . x ( ) > = workArea . x ( ) & & tl . y ( ) > = workArea . y ( )
& & tl . x ( ) > = workArea . x ( ) & & tl . y ( ) > = workArea . y ( )
& & tl . x ( ) + listView_ - > gridSize ( ) . width ( ) < = workArea . right ( ) + 1 // for historical reasons (-> Qt doc)
& & tl . x ( ) + itemSize . width ( ) < = workArea . right ( ) + 1 // for historical reasons (-> Qt doc)
& & tl . y ( ) + listView_ - > gridSize ( ) . height ( ) < = workArea . bottom ( ) + 1 ) { // as above
& & tl . y ( ) + itemSize . height ( ) < = workArea . bottom ( ) + 1 ) { // as above
QByteArray name = file . getName ( ) ;
customItemPos_ [ file - > name ( ) ] = tl ;
customItemPos_ [ name ] = tl ;
// qDebug() << "indexMoved:" << name << index << itemRect;
// qDebug() << "indexMoved:" << name << index << itemRect;
}
}
}
}
@ -490,10 +671,13 @@ void DesktopWindow::removeBottomGap() {
the vertical cell margin to prevent relatively large gaps
the vertical cell margin to prevent relatively large gaps
from taking shape at the desktop bottom .
from taking shape at the desktop bottom .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
auto delegate = static_cast < Fm : : FolderItemDelegate * > ( listView_ - > itemDelegateForColumn ( 0 ) ) ;
auto itemSize = delegate - > itemSize ( ) ;
qDebug ( ) < < " delegate: " < < delegate - > itemSize ( ) ;
QSize cellMargins = getMargins ( ) ;
QSize cellMargins = getMargins ( ) ;
int workAreaHeight = qApp - > desktop ( ) - > availableGeometry ( screenNum_ ) . height ( )
int workAreaHeight = qApp - > desktop ( ) - > availableGeometry ( screenNum_ ) . height ( )
- 24 ; // a 12-pix margin will be considered everywhere
- 24 ; // a 12-pix margin will be considered everywhere
int cellHeight = listView_ - > gridSize ( ) . height ( ) + listView_ - > spacing ( ) ;
int cellHeight = itemSize . height ( ) + listView_ - > spacing ( ) ;
int iconNumber = workAreaHeight / cellHeight ;
int iconNumber = workAreaHeight / cellHeight ;
int bottomGap = workAreaHeight % cellHeight ;
int bottomGap = workAreaHeight % cellHeight ;
/*******************************************
/*******************************************
@ -516,10 +700,11 @@ void DesktopWindow::removeBottomGap() {
/***************************************************
/***************************************************
. . . but if that can ' t be done , try to spread icons !
. . . but if that can ' t be done , try to spread icons !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
else
else {
cellMargins + = QSize ( 0 , ( bottomGap / iconNumber ) / 2 ) ;
cellMargins + = QSize ( 0 , ( bottomGap / iconNumber ) / 2 ) ;
}
// set the new margins (if they're changed)
// set the new margins (if they're changed)
delegate _ - > setMargins ( cellMargins ) ;
delegate - > setMargins ( cellMargins ) ;
setMargins ( cellMargins ) ;
setMargins ( cellMargins ) ;
// in case the text shadow is reset to (0,0,0,0)
// in case the text shadow is reset to (0,0,0,0)
setShadow ( settings . desktopShadowColor ( ) ) ;
setShadow ( settings . desktopShadowColor ( ) ) ;
@ -528,8 +713,7 @@ void DesktopWindow::removeBottomGap() {
void DesktopWindow : : paintBackground ( QPaintEvent * event ) {
void DesktopWindow : : paintBackground ( QPaintEvent * event ) {
// This is to workaround Qt bug 54384 which affects Qt >= 5.6
// This is to workaround Qt bug 54384 which affects Qt >= 5.6
// https://bugreports.qt.io/browse/QTBUG-54384
// https://bugreports.qt.io/browse/QTBUG-54384
// Since Qt does not paint the background of the QListView using the QPixmap we set properly, we do it ourselves.
QPainter painter ( this ) ;
QPainter painter ( listView_ - > viewport ( ) ) ; // the painter paints on the viewport widget, not the QListView.
if ( wallpaperMode_ = = WallpaperNone | | wallpaperPixmap_ . isNull ( ) ) {
if ( wallpaperMode_ = = WallpaperNone | | wallpaperPixmap_ . isNull ( ) ) {
painter . fillRect ( event - > rect ( ) , QBrush ( bgColor_ ) ) ;
painter . fillRect ( event - > rect ( ) , QBrush ( bgColor_ ) ) ;
}
}
@ -547,47 +731,53 @@ void DesktopWindow::relayoutItems() {
if ( relayoutTimer_ ) {
if ( relayoutTimer_ ) {
// this slot might be called from the timer, so we cannot delete it directly here.
// this slot might be called from the timer, so we cannot delete it directly here.
relayoutTimer_ - > deleteLater ( ) ;
relayoutTimer_ - > deleteLater ( ) ;
relayoutTimer_ = NULL ;
relayoutTimer_ = nullptr ;
}
}
QDesktopWidget * desktop = qApp - > desktop ( ) ;
QDesktopWidget * desktop = qApp - > desktop ( ) ;
int screen = 0 ;
int screen = 0 ;
int row = 0 ;
int row = 0 ;
int rowCount = proxyModel_ - > rowCount ( ) ;
int rowCount = proxyModel_ - > rowCount ( ) ;
auto delegate = static_cast < Fm : : FolderItemDelegate * > ( listView_ - > itemDelegateForColumn ( 0 ) ) ;
auto itemSize = delegate - > itemSize ( ) ;
for ( ; ; ) {
for ( ; ; ) {
if ( desktop - > isVirtualDesktop ( ) ) {
if ( desktop - > isVirtualDesktop ( ) ) {
if ( screen > = desktop - > numScreens ( ) )
if ( screen > = desktop - > numScreens ( ) ) {
break ;
break ;
} else {
}
}
else {
screen = screenNum_ ;
screen = screenNum_ ;
}
}
QRect workArea = desktop - > availableGeometry ( screen ) ;
QRect workArea = desktop - > availableGeometry ( screen ) ;
workArea . adjust ( 12 , 12 , - 12 , - 12 ) ; // add a 12 pixel margin to the work area
workArea . adjust ( 12 , 12 , - 12 , - 12 ) ; // add a 12 pixel margin to the work area
// qDebug() << "workArea" << screen << workArea;
// qDebug() << "workArea" << screen << workArea;
// FIXME: we use an internal class declared in a private header here, which is pretty bad.
// FIXME: we use an internal class declared in a private header here, which is pretty bad.
QSize grid = listView_ - > gridSize ( ) ;
QPoint pos = workArea . topLeft ( ) ;
QPoint pos = workArea . topLeft ( ) ;
for ( ; row < rowCount ; + + row ) {
for ( ; row < rowCount ; + + row ) {
QModelIndex index = proxyModel_ - > index ( row , 0 ) ;
QModelIndex index = proxyModel_ - > index ( row , 0 ) ;
int itemWidth = delegate _ - > sizeHint ( listView_ - > getViewOptions ( ) , index ) . width ( ) ;
int itemWidth = delegate - > sizeHint ( listView_ - > getViewOptions ( ) , index ) . width ( ) ;
Fm : : FileInf o file = proxyModel_ - > fileInfoFromIndex ( index ) ;
aut o file = proxyModel_ - > fileInfoFromIndex ( index ) ;
// remember display names of desktop entries and shortcuts
// remember display names of desktop entries and shortcuts
if ( file . isDesktopEntry ( ) | | file . isShortcut ( ) )
if ( file - > isDesktopEntry ( ) | | file - > isShortcut ( ) ) {
displayNames_ [ index ] = QString ( file . getDispName ( ) ) ;
displayNames_ [ index ] = file - > displayName ( ) ;
QByteArray name = file . getName ( ) ;
}
QHash < QByteArray , QPoint > : : iterator it = customItemPos_ . find ( name ) ;
auto name = file - > name ( ) ;
if ( it ! = customItemPos_ . end ( ) ) { // the item has a custom position
auto find_it = customItemPos_ . find ( name ) ;
QPoint customPos = * it ;
if ( find_it ! = customItemPos_ . cend ( ) ) { // the item has a custom position
QPoint customPos = find_it - > second ;
// center the contents vertically
// center the contents vertically
listView_ - > setPositionForIndex ( customPos + QPoint ( ( grid . width ( ) - itemWidth ) / 2 , 0 ) , index ) ;
listView_ - > setPositionForIndex ( customPos + QPoint ( ( itemSize . width ( ) - itemWidth ) / 2 , 0 ) , index ) ;
// qDebug() << "set custom pos:" << name << row << index << customPos;
// qDebug() << "set custom pos:" << name << row << index << customPos;
continue ;
continue ;
}
}
// check if the current pos is alredy occupied by a custom item
// check if the current pos is alredy occupied by a custom item
bool used = false ;
bool used = false ;
for ( it = customItemPos_ . begin( ) ; it ! = customItemPos_ . end( ) ; + + it ) {
for ( auto it = customItemPos_ . c begin( ) ; it ! = customItemPos_ . c end( ) ; + + it ) {
QPoint customPos = * it ;
QPoint customPos = it - > second ;
if ( QRect ( customPos , grid ) . contains ( pos ) ) {
if ( QRect ( customPos , itemSize ) . contains ( pos ) ) {
used = true ;
used = true ;
break ;
break ;
}
}
@ -597,18 +787,18 @@ void DesktopWindow::relayoutItems() {
}
}
else {
else {
// center the contents vertically
// center the contents vertically
listView_ - > setPositionForIndex ( pos + QPoint ( ( grid . width ( ) - itemWidth ) / 2 , 0 ) , index ) ;
listView_ - > setPositionForIndex ( pos + QPoint ( ( itemSize . width ( ) - itemWidth ) / 2 , 0 ) , index ) ;
// qDebug() << "set pos" << name << row << index << pos;
// qDebug() << "set pos" << name << row << index << pos;
}
}
// move to next cell in the column
// move to next cell in the column
pos . setY ( pos . y ( ) + grid . height ( ) + listView_ - > spacing ( ) ) ;
pos . setY ( pos . y ( ) + itemSize . height ( ) + listView_ - > spacing ( ) ) ;
if ( pos . y ( ) + grid . height ( ) > workArea . bottom ( ) + 1 ) {
if ( pos . y ( ) + itemSize . height ( ) > workArea . bottom ( ) + 1 ) {
// if the next position may exceed the bottom of work area, go to the top of next column
// if the next position may exceed the bottom of work area, go to the top of next column
pos . setX ( pos . x ( ) + grid . width ( ) + listView_ - > spacing ( ) ) ;
pos . setX ( pos . x ( ) + itemSize . width ( ) + listView_ - > spacing ( ) ) ;
pos . setY ( workArea . top ( ) ) ;
pos . setY ( workArea . top ( ) ) ;
// check if the new column exceeds the right margin of work area
// check if the new column exceeds the right margin of work area
if ( pos . x ( ) + grid . width ( ) > workArea . right ( ) + 1 ) {
if ( pos . x ( ) + itemSize . width ( ) > workArea . right ( ) + 1 ) {
if ( desktop - > isVirtualDesktop ( ) ) {
if ( desktop - > isVirtualDesktop ( ) ) {
// in virtual desktop mode, go to next screen
// in virtual desktop mode, go to next screen
+ + screen ;
+ + screen ;
@ -617,23 +807,37 @@ void DesktopWindow::relayoutItems() {
}
}
}
}
}
}
if ( row > = rowCount )
if ( row > = rowCount ) {
break ;
break ;
}
}
}
}
if ( ! listView_ - > updatesEnabled ( ) ) {
listView_ - > setUpdatesEnabled ( true ) ;
}
}
void DesktopWindow : : loadItemPositions ( ) {
void DesktopWindow : : loadItemPositions ( ) {
// load custom item positions
// load custom item positions
customItemPos_ . clear ( ) ;
customItemPos_ . clear ( ) ;
Settings & settings = static_cast < Application * > ( qApp ) - > settings ( ) ;
Settings & settings = static_cast < Application * > ( qApp ) - > settings ( ) ;
QString configFile = QString ( " %1/desktop-items-%2.conf " ) . arg ( settings . profileDir ( settings . profileName ( ) ) ) . arg ( screenNum_ ) ;
QString configFile = QString ( " %1/desktop-items-%2.conf " ) . arg ( settings . profileDir ( settings . profileName ( ) ) ) . arg ( screenNum_ ) ;
QSettings file ( configFile , QSettings : : IniFormat ) ;
QSettings file ( configFile , QSettings : : IniFormat ) ;
QSize grid = listView_ - > gridSize ( ) ;
auto delegate = static_cast < Fm : : FolderItemDelegate * > ( listView_ - > itemDelegateForColumn ( 0 ) ) ;
auto grid = delegate - > itemSize ( ) ;
QRect workArea = qApp - > desktop ( ) - > availableGeometry ( screenNum_ ) ;
QRect workArea = qApp - > desktop ( ) - > availableGeometry ( screenNum_ ) ;
workArea . adjust ( 12 , 12 , - 12 , - 12 ) ;
workArea . adjust ( 12 , 12 , - 12 , - 12 ) ;
char * dektopPath = Fm : : Path : : getDesktop ( ) . toStr ( ) ;
char * dektopPath = Fm : : Path : : getDesktop ( ) . toStr ( ) ;
QString desktopDir = QString ( dektopPath ) + QString ( " / " ) ;
QString desktopDir = QString ( dektopPath ) + QString ( " / " ) ;
g_free ( dektopPath ) ;
g_free ( dektopPath ) ;
std : : vector < QPoint > usedPos ;
for ( auto & item : customItemPos_ ) {
usedPos . push_back ( item . second ) ;
}
// FIXME: this is inefficient
Q_FOREACH ( const QString & name , file . childGroups ( ) ) {
Q_FOREACH ( const QString & name , file . childGroups ( ) ) {
if ( ! QFile : : exists ( desktopDir + name . toUtf8 ( ) ) ) {
if ( ! QFile : : exists ( desktopDir + name . toUtf8 ( ) ) ) {
// the file may have been removed from outside LXQT
// the file may have been removed from outside LXQT
@ -644,24 +848,20 @@ void DesktopWindow::loadItemPositions() {
if ( var . isValid ( ) ) {
if ( var . isValid ( ) ) {
QPoint customPos = var . toPoint ( ) ;
QPoint customPos = var . toPoint ( ) ;
if ( customPos . x ( ) > = workArea . x ( ) & & customPos . y ( ) > = workArea . y ( )
if ( customPos . x ( ) > = workArea . x ( ) & & customPos . y ( ) > = workArea . y ( )
& & customPos . x ( ) + listView_ - > gridSize ( ) . width ( ) < = workArea . right ( ) + 1
& & customPos . x ( ) + grid . width ( ) < = workArea . right ( ) + 1
& & customPos . y ( ) + listView_ - > gridSize ( ) . height ( ) < = workArea . bottom ( ) + 1 )
& & customPos . y ( ) + grid . height ( ) < = workArea . bottom ( ) + 1 ) {
{
// correct positions that are't aligned to the grid
// correct positions that are't aligned to the grid
qreal w = qAbs ( ( qreal ) customPos . x ( ) - ( qreal ) workArea . x ( ) )
alignToGrid ( customPos , workArea . topLeft ( ) , grid , listView_ - > spacing ( ) ) ;
/ ( qreal ) ( grid . width ( ) + listView_ - > spacing ( ) ) ;
// FIXME: this is very inefficient
qreal h = qAbs ( customPos . y ( ) - ( qreal ) workArea . y ( ) )
while ( std : : find ( usedPos . cbegin ( ) , usedPos . cend ( ) , customPos ) ! = usedPos . cend ( ) ) {
/ ( qreal ) ( grid . height ( ) + listView_ - > spacing ( ) ) ;
customPos . setX ( workArea . x ( ) + qRound ( w ) * ( grid . width ( ) + listView_ - > spacing ( ) ) ) ;
customPos . setY ( workArea . y ( ) + qRound ( h ) * ( grid . height ( ) + listView_ - > spacing ( ) ) ) ;
while ( customItemPos_ . values ( ) . contains ( customPos ) ) {
customPos . setY ( customPos . y ( ) + grid . height ( ) + listView_ - > spacing ( ) ) ;
customPos . setY ( customPos . y ( ) + grid . height ( ) + listView_ - > spacing ( ) ) ;
if ( customPos . y ( ) + grid . height ( ) > workArea . bottom ( ) + 1 ) {
if ( customPos . y ( ) + grid . height ( ) > workArea . bottom ( ) + 1 ) {
customPos . setX ( customPos . x ( ) + grid . width ( ) + listView_ - > spacing ( ) ) ;
customPos . setX ( customPos . x ( ) + grid . width ( ) + listView_ - > spacing ( ) ) ;
customPos . setY ( workArea . top ( ) ) ;
customPos . setY ( workArea . top ( ) ) ;
}
}
}
}
customItemPos_ [ name . toUtf8 ( ) ] = customPos ;
customItemPos_ [ name . toStdString ( ) ] = customPos ;
usedPos . push_back ( customPos ) ;
}
}
}
}
file . endGroup ( ) ;
file . endGroup ( ) ;
@ -677,40 +877,41 @@ void DesktopWindow::saveItemPositions() {
file . clear ( ) ; // remove all existing entries
file . clear ( ) ; // remove all existing entries
// FIXME: we have to remove dead entries not associated to any files?
// FIXME: we have to remove dead entries not associated to any files?
QHash < QByteArray , QPoint > : : iterator it ;
for ( auto it = customItemPos_ . cbegin ( ) ; it ! = customItemPos_ . cend ( ) ; + + it ) {
for ( it = customItemPos_ . begin ( ) ; it ! = customItemPos_ . end ( ) ; + + it ) {
auto & name = it - > first ;
const QByteArray & name = it . key ( ) ;
auto & pos = it - > second ;
QPoint pos = it . value ( ) ;
file . beginGroup ( QString : : fromStdString ( name ) ) ;
file . beginGroup ( QString : : fromUtf8 ( name , name . length ( ) ) ) ;
file . setValue ( " pos " , pos ) ;
file . setValue ( " pos " , pos ) ;
file . endGroup ( ) ;
file . endGroup ( ) ;
}
}
}
}
void DesktopWindow : : onStickToCurrentPos ( bool toggled ) {
void DesktopWindow : : onStickToCurrentPos ( bool toggled ) {
QAction * action = static_cast < QAction * > ( sender ( ) ) ;
Fm : : FileMenu * menu = static_cast < Fm : : FileMenu * > ( action - > parent ( ) ) ;
QModelIndexList indexes = listView_ - > selectionModel ( ) - > selectedIndexes ( ) ;
QModelIndexList indexes = listView_ - > selectionModel ( ) - > selectedIndexes ( ) ;
if ( ! indexes . isEmpty ( ) ) {
if ( ! indexes . isEmpty ( ) ) {
Fm : : FileInfo file = menu - > firstFile ( ) ;
bool relayout ( false ) ;
QByteArray name = file . getName ( ) ;
QModelIndexList : : const_iterator it ;
QModelIndex index = indexes . first ( ) ;
for ( it = indexes . constBegin ( ) ; it ! = indexes . constEnd ( ) ; + + it ) {
if ( toggled ) { // remember to current custom position
auto file = proxyModel_ - > fileInfoFromIndex ( * it ) ;
QRect itemRect = listView_ - > rectForIndex ( index ) ;
auto name = file - > name ( ) ;
if ( toggled ) { // remember the current custom position
QRect itemRect = listView_ - > rectForIndex ( * it ) ;
customItemPos_ [ name ] = itemRect . topLeft ( ) ;
customItemPos_ [ name ] = itemRect . topLeft ( ) ;
saveItemPositions ( ) ;
}
}
else { // cancel custom position and perform relayout
else { // cancel custom position and perform relayout
QHash < QByteArray , QPoint > : : iterator it = customItemPos_ . find ( name ) ;
auto item = customItemPos_ . find ( name ) ;
if ( it ! = customItemPos_ . end ( ) ) {
if ( item ! = customItemPos_ . end ( ) ) {
customItemPos_ . erase ( it ) ;
customItemPos_ . erase ( item ) ;
relayout = true ;
}
}
}
saveItemPositions ( ) ;
saveItemPositions ( ) ;
if ( relayout ) {
relayoutItems ( ) ;
relayoutItems ( ) ;
}
}
}
}
}
}
}
void DesktopWindow : : queueRelayout ( int delay ) {
void DesktopWindow : : queueRelayout ( int delay ) {
// qDebug() << "queueRelayout";
// qDebug() << "queueRelayout";
@ -726,15 +927,15 @@ void DesktopWindow::queueRelayout(int delay) {
// slots for file operations
// slots for file operations
void DesktopWindow : : onCutActivated ( ) {
void DesktopWindow : : onCutActivated ( ) {
Fm : : PathList paths = selectedFilePaths ( ) ;
auto paths = selectedFilePaths ( ) ;
if ( ! paths . isNull ( ) ) {
if ( ! paths . empty ( ) ) {
Fm : : cutFilesToClipboard ( paths ) ;
Fm : : cutFilesToClipboard ( paths ) ;
}
}
}
}
void DesktopWindow : : onCopyActivated ( ) {
void DesktopWindow : : onCopyActivated ( ) {
Fm : : PathList paths = selectedFilePaths ( ) ;
auto paths = selectedFilePaths ( ) ;
if ( ! paths . isNull ( ) ) {
if ( ! paths . empty ( ) ) {
Fm : : copyFilesToClipboard ( paths ) ;
Fm : : copyFilesToClipboard ( paths ) ;
}
}
}
}
@ -744,31 +945,41 @@ void DesktopWindow::onPasteActivated() {
}
}
void DesktopWindow : : onDeleteActivated ( ) {
void DesktopWindow : : onDeleteActivated ( ) {
Fm : : PathList paths = selectedFilePaths ( ) ;
auto paths = selectedFilePaths ( ) ;
if ( ! paths . isNull ( ) ) {
if ( ! paths . empty ( ) ) {
Settings & settings = static_cast < Application * > ( qApp ) - > settings ( ) ;
Settings & settings = static_cast < Application * > ( qApp ) - > settings ( ) ;
bool shiftPressed = ( qApp - > keyboardModifiers ( ) & Qt : : ShiftModifier ? true : false ) ;
bool shiftPressed = ( qApp - > keyboardModifiers ( ) & Qt : : ShiftModifier ? true : false ) ;
if ( settings . useTrash ( ) & & ! shiftPressed )
if ( settings . useTrash ( ) & & ! shiftPressed ) {
Fm : : FileOperation : : trashFiles ( paths , settings . confirmTrash ( ) ) ;
Fm : : FileOperation : : trashFiles ( paths , settings . confirmTrash ( ) ) ;
else
}
else {
Fm : : FileOperation : : deleteFiles ( paths , settings . confirmDelete ( ) ) ;
Fm : : FileOperation : : deleteFiles ( paths , settings . confirmDelete ( ) ) ;
}
}
}
}
}
void DesktopWindow : : onRenameActivated ( ) {
void DesktopWindow : : onRenameActivated ( ) {
Fm : : FileInfoList files = selectedFiles ( ) ;
// do inline renaming if only one item is selected,
if ( ! files . isNull ( ) ) {
// otherwise use the renaming dialog
for ( GList * l = fm_file_info_list_peek_head_link ( files ) ; l ; l = l - > next ) {
if ( selectedIndexes ( ) . size ( ) = = 1 ) {
FmFileInfo * info = FM_FILE_INFO ( l - > data ) ;
QModelIndex cur = listView_ - > currentIndex ( ) ;
Fm : : renameFile ( info , NULL ) ;
if ( cur . isValid ( ) ) {
listView_ - > edit ( cur ) ;
return ;
}
}
auto files = selectedFiles ( ) ;
if ( ! files . empty ( ) ) {
for ( auto & info : files ) {
Fm : : renameFile ( info , nullptr ) ;
}
}
}
}
}
}
void DesktopWindow : : onFilePropertiesActivated ( ) {
void DesktopWindow : : onFilePropertiesActivated ( ) {
Fm : : FileInfoList files = selectedFiles ( ) ;
auto files = selectedFiles ( ) ;
if ( ! files . isNull ( ) ) {
if ( ! files . empty ( ) ) {
Fm : : FilePropsDialog : : showForFiles ( files ) ;
Fm : : FilePropsDialog : : showForFiles ( std: : move ( files) ) ;
}
}
}
}
@ -810,12 +1021,15 @@ static void forwardMouseEventToRoot(QMouseEvent* event) {
}
}
// convert Qt modifiers to XCB states
// convert Qt modifiers to XCB states
if ( event - > modifiers ( ) & Qt : : ShiftModifier )
if ( event - > modifiers ( ) & Qt : : ShiftModifier ) {
xcb_event . state | = XCB_MOD_MASK_SHIFT ;
xcb_event . state | = XCB_MOD_MASK_SHIFT ;
if ( event - > modifiers ( ) & Qt : : ControlModifier )
}
if ( event - > modifiers ( ) & Qt : : ControlModifier ) {
xcb_event . state | = XCB_MOD_MASK_SHIFT ;
xcb_event . state | = XCB_MOD_MASK_SHIFT ;
if ( event - > modifiers ( ) & Qt : : AltModifier )
}
if ( event - > modifiers ( ) & Qt : : AltModifier ) {
xcb_event . state | = XCB_MOD_MASK_1 ;
xcb_event . state | = XCB_MOD_MASK_1 ;
}
xcb_event . sequence = 0 ;
xcb_event . sequence = 0 ;
xcb_event . time = event - > timestamp ( ) ;
xcb_event . time = event - > timestamp ( ) ;
@ -835,20 +1049,20 @@ static void forwardMouseEventToRoot(QMouseEvent* event) {
xcb_flush ( QX11Info : : connection ( ) ) ;
xcb_flush ( QX11Info : : connection ( ) ) ;
}
}
bool DesktopWindow : : event ( QEvent * event )
bool DesktopWindow : : event ( QEvent * event ) {
{
switch ( event - > type ( ) ) {
switch ( event - > type ( ) ) {
case QEvent : : WinIdChange : {
case QEvent : : WinIdChange : {
qDebug ( ) < < " winid change: " < < effectiveWinId ( ) ;
qDebug ( ) < < " winid change: " < < effectiveWinId ( ) ;
if ( effectiveWinId ( ) = = 0 )
if ( effectiveWinId ( ) = = 0 ) {
break ;
break ;
}
// set freedesktop.org EWMH hints properly
// set freedesktop.org EWMH hints properly
if ( QX11Info : : isPlatformX11 ( ) & & QX11Info : : connection ( ) ) {
if ( QX11Info : : isPlatformX11 ( ) & & QX11Info : : connection ( ) ) {
xcb_connection_t * con = QX11Info : : connection ( ) ;
xcb_connection_t * con = QX11Info : : connection ( ) ;
const char * atom_name = " _NET_WM_WINDOW_TYPE_DESKTOP " ;
const char * atom_name = " _NET_WM_WINDOW_TYPE_DESKTOP " ;
xcb_atom_t atom = xcb_intern_atom_reply ( con , xcb_intern_atom ( con , 0 , strlen ( atom_name ) , atom_name ) , NULL ) - > atom ;
xcb_atom_t atom = xcb_intern_atom_reply ( con , xcb_intern_atom ( con , 0 , strlen ( atom_name ) , atom_name ) , nullptr ) - > atom ;
const char * prop_atom_name = " _NET_WM_WINDOW_TYPE " ;
const char * prop_atom_name = " _NET_WM_WINDOW_TYPE " ;
xcb_atom_t prop_atom = xcb_intern_atom_reply ( con , xcb_intern_atom ( con , 0 , strlen ( prop_atom_name ) , prop_atom_name ) , NULL ) - > atom ;
xcb_atom_t prop_atom = xcb_intern_atom_reply ( con , xcb_intern_atom ( con , 0 , strlen ( prop_atom_name ) , prop_atom_name ) , nullptr ) - > atom ;
xcb_atom_t XA_ATOM = 4 ;
xcb_atom_t XA_ATOM = 4 ;
xcb_change_property ( con , XCB_PROP_MODE_REPLACE , effectiveWinId ( ) , prop_atom , XA_ATOM , 32 , 1 , & atom ) ;
xcb_change_property ( con , XCB_PROP_MODE_REPLACE , effectiveWinId ( ) , prop_atom , XA_ATOM , 32 , 1 , & atom ) ;
}
}
@ -874,8 +1088,9 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
switch ( event - > type ( ) ) {
switch ( event - > type ( ) ) {
case QEvent : : StyleChange :
case QEvent : : StyleChange :
case QEvent : : FontChange :
case QEvent : : FontChange :
if ( model_ )
if ( model_ ) {
queueRelayout ( ) ;
queueRelayout ( ) ;
}
break ;
break ;
default :
default :
break ;
break ;
@ -883,10 +1098,6 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
}
}
else if ( watched = = listView_ - > viewport ( ) ) {
else if ( watched = = listView_ - > viewport ( ) ) {
switch ( event - > type ( ) ) {
switch ( event - > type ( ) ) {
case QEvent : : Paint : {
paintBackground ( static_cast < QPaintEvent * > ( event ) ) ;
break ;
}
case QEvent : : MouseButtonPress :
case QEvent : : MouseButtonPress :
case QEvent : : MouseButtonRelease :
case QEvent : : MouseButtonRelease :
if ( showWmMenu_ ) {
if ( showWmMenu_ ) {
@ -904,15 +1115,15 @@ bool DesktopWindow::eventFilter(QObject * watched, QEvent * event) {
break ;
break ;
}
}
}
}
return false ;
return Fm : : FolderView : : eventFilter ( watched , event ) ;
}
}
void DesktopWindow : : childDropEvent ( QDropEvent * e ) {
void DesktopWindow : : childDropEvent ( QDropEvent * e ) {
const QMimeData * mimeData = e - > mimeData ( ) ;
bool moveItem = false ;
bool moveItem = false ;
if ( e - > source ( ) = = listView_ & & e - > keyboardModifiers ( ) = = Qt : : NoModifier ) {
if ( e - > source ( ) = = listView_ & & e - > keyboardModifiers ( ) = = Qt : : NoModifier ) {
// drag source is our list view, and no other modifier keys are pressed
// drag source is our list view, and no other modifier keys are pressed
// => we're dragging desktop items
// => we're dragging desktop items
const QMimeData * mimeData = e - > mimeData ( ) ;
if ( mimeData - > hasFormat ( " application/x-qabstractitemmodeldatalist " ) ) {
if ( mimeData - > hasFormat ( " application/x-qabstractitemmodeldatalist " ) ) {
QModelIndex dropIndex = listView_ - > indexAt ( e - > pos ( ) ) ;
QModelIndex dropIndex = listView_ - > indexAt ( e - > pos ( ) ) ;
if ( dropIndex . isValid ( ) ) { // drop on an item
if ( dropIndex . isValid ( ) ) { // drop on an item
@ -926,10 +1137,50 @@ void DesktopWindow::childDropEvent(QDropEvent* e) {
}
}
}
}
}
}
if ( moveItem )
if ( moveItem ) {
e - > accept ( ) ;
e - > accept ( ) ;
else
}
else {
auto delegate = static_cast < Fm : : FolderItemDelegate * > ( listView_ - > itemDelegateForColumn ( 0 ) ) ;
auto grid = delegate - > itemSize ( ) ;
Fm : : FolderView : : childDropEvent ( e ) ;
Fm : : FolderView : : childDropEvent ( e ) ;
// position dropped items successively, starting with the drop rectangle
if ( mimeData - > hasUrls ( )
& & ( e - > dropAction ( ) = = Qt : : CopyAction
| | e - > dropAction ( ) = = Qt : : MoveAction
| | e - > dropAction ( ) = = Qt : : LinkAction ) ) {
QList < QUrl > urlList = mimeData - > urls ( ) ;
for ( int i = 0 ; i < urlList . count ( ) ; + + i ) {
std : : string name = urlList . at ( i ) . fileName ( ) . toUtf8 ( ) . constData ( ) ;
if ( ! name . empty ( ) ) { // respect the positions of existing files
QString desktopDir = XdgDir : : readDesktopDir ( ) + QString ( QLatin1String ( " / " ) ) ;
if ( ! QFile : : exists ( desktopDir + QString : : fromStdString ( name ) ) ) {
QRect workArea = qApp - > desktop ( ) - > availableGeometry ( screenNum_ ) ;
workArea . adjust ( 12 , 12 , - 12 , - 12 ) ;
QPoint pos = mapFromGlobal ( e - > pos ( ) ) ;
alignToGrid ( pos , workArea . topLeft ( ) , grid , listView_ - > spacing ( ) ) ;
if ( i > 0 )
pos . setY ( pos . y ( ) + grid . height ( ) + listView_ - > spacing ( ) ) ;
if ( pos . y ( ) + grid . height ( ) > workArea . bottom ( ) + 1 ) {
pos . setX ( pos . x ( ) + grid . width ( ) + listView_ - > spacing ( ) ) ;
pos . setY ( workArea . top ( ) ) ;
}
customItemPos_ [ name ] = pos ;
}
}
}
saveItemPositions ( ) ;
}
}
}
void DesktopWindow : : alignToGrid ( QPoint & pos , const QPoint & topLeft , const QSize & grid , const int spacing ) {
qreal w = qAbs ( ( qreal ) pos . x ( ) - ( qreal ) topLeft . x ( ) )
/ ( qreal ) ( grid . width ( ) + spacing ) ;
qreal h = qAbs ( pos . y ( ) - ( qreal ) topLeft . y ( ) )
/ ( qreal ) ( grid . height ( ) + spacing ) ;
pos . setX ( topLeft . x ( ) + qRound ( w ) * ( grid . width ( ) + spacing ) ) ;
pos . setY ( topLeft . y ( ) + qRound ( h ) * ( grid . height ( ) + spacing ) ) ;
}
}
void DesktopWindow : : closeEvent ( QCloseEvent * event ) {
void DesktopWindow : : closeEvent ( QCloseEvent * event ) {
@ -937,6 +1188,11 @@ void DesktopWindow::closeEvent(QCloseEvent *event) {
event - > ignore ( ) ;
event - > ignore ( ) ;
}
}
void DesktopWindow : : paintEvent ( QPaintEvent * event ) {
paintBackground ( event ) ;
QWidget : : paintEvent ( event ) ;
}
void DesktopWindow : : setScreenNum ( int num ) {
void DesktopWindow : : setScreenNum ( int num ) {
if ( screenNum_ ! = num ) {
if ( screenNum_ ! = num ) {
screenNum_ = num ;
screenNum_ = num ;