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);
}
Example #6
0
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.
}
Example #10
0
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();
}
Example #11
0
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();
}
Example #12
0
void DesktopWindow::onLayoutChanged() {
    queueRelayout();
}
Example #13
0
void DesktopWindow::setScreenNum(int num) {
    if(screenNum_ != num) {
        screenNum_ = num;
        queueRelayout();
    }
}
Example #14
0
void DesktopWindow::onRowsInserted(const QModelIndex& parent, int start, int end) {
  queueRelayout();
}