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 Q_FOREACH(const QModelIndex& index, indexes) { // Under some circumstances, Qt might emit indexMoved for // every single cells in the same row. (when QAbstractItemView::SelectItems is set) // So indexes list may contain several indixes for the same row. // Since we only care about rows, not individual cells, // let's handle column 0 of every row here. if(index.column() == 0) { auto file = proxyModel_->fileInfoFromIndex(index); QRect itemRect = listView_->rectForIndex(index); QPoint tl = itemRect.topLeft(); QRect workArea = qApp->desktop()->availableGeometry(screenNum_); workArea.adjust(12, 12, -12, -12); // 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() + itemSize.width() <= workArea.right() + 1 // for historical reasons (-> Qt doc) && tl.y() + itemSize.height() <= workArea.bottom() + 1) { // as above customItemPos_[file->name()] = tl; // qDebug() << "indexMoved:" << name << index << itemRect; } } } saveItemPositions(); queueRelayout(); }
bool DesktopWindow::eventFilter(QObject* watched, QEvent* event) { if(watched == listView_) { switch(event->type()) { case QEvent::StyleChange: case QEvent::FontChange: if(model_) { queueRelayout(); } break; default: break; } } else if(watched == listView_->viewport()) { switch(event->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: if(showWmMenu_) { QMouseEvent* e = static_cast<QMouseEvent*>(event); // If we want to show the desktop menus provided by the window manager instead of ours, // we have to forward the mouse events we received to the root window. // check if the user click on blank area QModelIndex index = listView_->indexAt(e->pos()); if(!index.isValid() && e->button() != Qt::LeftButton) { forwardMouseEventToRoot(e); } } break; default: break; } } return Fm::FolderView::eventFilter(watched, event); }
void DesktopWindow::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { /**************************************************************************** NOTE: The display names of desktop entries and shortcuts may change without their files being renamed and, on such occasions, a relayout will be needed. Since there is no signal for that, we use the signal dataChanged() and the QHash displayNames_, which remembers such display names with every relayout. ****************************************************************************/ if(topLeft.column() == 0) { bool relayout(false); for(int i = topLeft.row(); i <= bottomRight.row(); ++i) { QModelIndex index = topLeft.sibling(i, 0); if(index.isValid() && displayNames_.contains(index)) { auto file = proxyModel_->fileInfoFromIndex(index); if(displayNames_[index] != file->displayName()) { relayout = true; break; } } } if(relayout) { queueRelayout(); // parts of the old display name might still be visible if it's long listView_->viewport()->update(); } } }
void DesktopWindow::onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); if(!customItemPos_.empty()) { // also delete stored custom item positions for the items currently being removed. // Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows // aren't removed yet, files are already removed. bool changed = false; char* dektopPath = Fm::Path::getDesktop().toStr(); QString desktopDir = QString(dektopPath) + QString("/"); g_free(dektopPath); for(auto it = customItemPos_.cbegin(); it != customItemPos_.cend();) { auto& name = it->first; if(!QFile::exists(desktopDir + QString::fromStdString(name))) { it = customItemPos_.erase(it); changed = true; } else { ++it; } } if(changed) { saveItemPositions(); } } listView_->setUpdatesEnabled(false); queueRelayout(100); }
bool DesktopWindow::event(QEvent* event) { switch(event->type()) { case QEvent::WinIdChange: { qDebug() << "winid change:" << effectiveWinId(); if(effectiveWinId() == 0) { break; } // set freedesktop.org EWMH hints properly if(QX11Info::isPlatformX11() && QX11Info::connection()) { xcb_connection_t* con = QX11Info::connection(); 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), nullptr)->atom; 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), nullptr)->atom; xcb_atom_t XA_ATOM = 4; xcb_change_property(con, XCB_PROP_MODE_REPLACE, effectiveWinId(), prop_atom, XA_ATOM, 32, 1, &atom); } break; } #undef FontChange // FontChange is defined in the headers of XLib and clashes with Qt, let's undefine it. case QEvent::StyleChange: case QEvent::FontChange: queueRelayout(); break; default: break; } return QWidget::event(event); }
void DesktopWindow::onIndexesMoved(const QModelIndexList& indexes) { // remember the custom position for the items Q_FOREACH(const QModelIndex& index, indexes) { // Under some circumstances, Qt might emit indexMoved for // every single cells in the same row. (when QAbstractItemView::SelectItems is set) // So indexes list may contain several indixes for the same row. // Since we only care about rows, not individual cells, // let's handle column 0 of every row here. if(index.column() == 0) { FmFileInfo* file = proxyModel_->fileInfoFromIndex(index); QRect itemRect = listView_->rectForIndex(index); QPoint tl = itemRect.topLeft(); QRect workArea = qApp->desktop()->availableGeometry(screenNum_); workArea.adjust(12, 12, -12, -12); if(customItemPos_.keys(tl).isEmpty() // don't put items on each other && tl.x() >= workArea.x() && tl.y() >= workArea.y() && tl.x() + listView_->gridSize().width() <= workArea.right() + 1 // for historical reasons (-> Qt doc) && tl.y() + listView_->gridSize().height() <= workArea.bottom() + 1) { // as above QByteArray name = fm_file_info_get_name(file); customItemPos_[name] = tl; // qDebug() << "indexMoved:" << name << index << itemRect; } } } saveItemPositions(); queueRelayout(); }
void DesktopWindow::updateFromSettings(Settings& settings, bool changeSlide) { setDesktopFolder(); setWallpaperFile(settings.wallpaper()); 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()); setIconSize(Fm::FolderView::IconMode, QSize(settings.desktopIconSize(), settings.desktopIconSize())); setMargins(settings.desktopCellMargins()); // setIconSize and setMargins may trigger relayout of items by QListView, so we need to do the layout again. queueRelayout(); setForeground(settings.desktopFgColor()); setBackground(settings.desktopBgColor()); setShadow(settings.desktopShadowColor()); 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(); update(); if(wallpaperTimer_) { wallpaperTimer_->start(slideShowInterval_); } }
void DesktopWindow::onRowsInserted(const QModelIndex& parent, int start, int end) { 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::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); // resize wall paper if needed if(isVisible() && wallpaperMode_ != WallpaperNone && wallpaperMode_ != WallpaperTile) { updateWallpaper(); update(); } queueRelayout(100); // Qt use a 100 msec delay for relayout internally so we use it, too. }
void DesktopWindow::updateFromSettings(Settings& settings) { setDesktopFolder(); setWallpaperFile(settings.wallpaper()); setWallpaperMode(settings.wallpaperMode()); setFont(settings.desktopFont()); setIconSize(Fm::FolderView::IconMode, QSize(settings.desktopIconSize(), settings.desktopIconSize())); setMargins(settings.desktopCellMargins()); // setIconSize and setMargins may trigger relayout of items by QListView, so we need to do the layout again. queueRelayout(); setForeground(settings.desktopFgColor()); setBackground(settings.desktopBgColor()); setShadow(settings.desktopShadowColor()); showWmMenu_ = settings.showWmMenu(); updateWallpaper(); update(); }
void DesktopWindow::onRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); if(!customItemPos_.isEmpty()) { // also delete stored custom item positions for the items currently being removed. // Here we can't rely on ProxyFolderModel::fileInfoFromIndex() because, although rows // aren't removed yet, files are already removed. QHash<QByteArray, QPoint> _customItemPos = customItemPos_; char* dektopPath = fm_path_to_str(fm_path_get_desktop()); QString desktopDir = QString(dektopPath) + QString("/"); g_free(dektopPath); QHash<QByteArray, QPoint>::iterator it; for(it = _customItemPos.begin(); it != _customItemPos.end(); ++it) { const QByteArray& name = it.key(); if(!QFile::exists(desktopDir + QString::fromUtf8(name, name.length()))) customItemPos_.remove(it.key()); } if(customItemPos_ != _customItemPos) saveItemPositions(); } queueRelayout(); }
void DesktopWindow::onLayoutChanged() { queueRelayout(); }
void DesktopWindow::setScreenNum(int num) { if(screenNum_ != num) { screenNum_ = num; queueRelayout(); } }
void DesktopWindow::onRowsInserted(const QModelIndex& parent, int start, int end) { queueRelayout(); }