Example #1
0
/*****************************************************************************************
 *  Add a FileInfo to the parent node to the proper position.
 *  tree_path is the tree path of the parent node.
 * 
 ****************************************************************************************/
GList *fm_dir_tree_model_insert_file_info (FmDirTreeModel *dir_tree_model, GList *parent_node,
                                           GtkTreePath *tree_path, FmFileInfo *file_info)
{
    FmDirTreeItem *parent_item = (FmDirTreeItem*) parent_node->data;
    
    FmDirTreeItem *dir_tree_item = fm_dir_tree_item_new (dir_tree_model, parent_node, file_info);

    // Don't show hidden files...
    if (!dir_tree_model->show_hidden && file_info->path->name[0] == '.')
    {
        parent_item->hidden_children = g_list_prepend (parent_item->hidden_children, dir_tree_item);
        return parent_item->hidden_children;
    }
    
    // Don't show links...
    if (!dir_tree_model->show_symlinks && fm_file_info_is_symlink (file_info))
    {
        parent_item->hidden_children = g_list_prepend (parent_item->hidden_children, dir_tree_item);
        return parent_item->hidden_children;
    }
    
    GList *item_list = fm_dir_tree_model_insert_sorted (dir_tree_model, parent_node, tree_path, dir_tree_item);
    
    char *tmp_path = gtk_tree_path_to_string (tree_path);
    TREEVIEW_DEBUG ("TREEVIEW_DEBUG: fm_dir_tree_model_insert_file_info: file = %s\t index = %d\n\n",
                    fm_file_info_get_name (file_info), file_info->sorting_index);
    g_free (tmp_path);
    
    return item_list;
}
Example #2
0
static void fm_dir_tree_model_add_place_holder_child_item (FmDirTreeModel *dir_tree_model, GList *parent_node,
                                                           GtkTreePath *tree_path, gboolean emit_signal)
{
    FmDirTreeItem *parent_item = (FmDirTreeItem*) parent_node->data;
    
    // Check if the parent node can expand...
    FmFileInfo *file_info = parent_item->file_info;
    FmPath *path = fm_file_info_get_path (file_info);
    
    TREEVIEW_DEBUG ("TREEVIEW_DEBUG: fm_dir_tree_model_add_place_holder_child_item: file = %s\t emit_signal = %d\n",
                    fm_file_info_get_name (file_info), emit_signal);
    
    
    // don't expand the trash can...
    // TODO_axl: add a can_expand flag into the file_info
    if (fm_path_is_trash (path) && fm_path_is_root (path))
        return;
    
    TREEVIEW_DEBUG ("TREEVIEW_DEBUG: fm_dir_tree_model_add_place_holder_child_item: create place holder\n\n");
    
    FmDirTreeItem *dir_tree_item = fm_dir_tree_item_new (dir_tree_model, parent_node, NULL);
    
    parent_item->children = g_list_prepend (parent_item->children, dir_tree_item);

    if (!emit_signal)
        return;
        
    GtkTreeIter it;
    fm_dir_tree_model_item_to_tree_iter (dir_tree_model, parent_item->children, &it);
    
    gtk_tree_path_append_index (tree_path, 0);
    
    gtk_tree_model_row_inserted (GTK_TREE_MODEL (dir_tree_model), tree_path, &it);
    gtk_tree_path_up (tree_path);
}
Example #3
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();
}
bool ProxyFilter::filterAcceptsRow(const Fm::ProxyFolderModel* model, FmFileInfo* info) const {
  if(!model || !info)
    return true;
  QString baseName(fm_file_info_get_name(info));
  if(!virtHiddenList_.isEmpty() && !model->showHidden() && virtHiddenList_.contains(baseName))
      return false;
  if(!filterStr_.isEmpty() && !baseName.contains(filterStr_, Qt::CaseInsensitive))
    return false;
  return true;
}
Example #5
0
void DesktopWindow::prepareFileMenu(Fm::FileMenu* menu) {
  // qDebug("DesktopWindow::prepareFileMenu");
  PCManFM::View::prepareFileMenu(menu);
  QAction* action = new QAction(tr("Stic&k to Current Position"), menu);
  action->setCheckable(true);
  menu->insertSeparator(menu->separator2());
  menu->insertAction(menu->separator2(), action);

  FmFileInfoList* files = menu->files();
  // select exactly one item
  if(fm_file_info_list_get_length(files) == 1) {
    FmFileInfo* file = menu->firstFile();
    if(customItemPos_.find(fm_file_info_get_name(file)) != customItemPos_.end()) {
      // the file item has a custom position
      action->setChecked(true);
    }
  }
  connect(action, &QAction::toggled, this, &DesktopWindow::onStickToCurrentPos);
}
Example #6
0
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();
  if(!indexes.isEmpty()) {
    FmFileInfo* file = menu->firstFile();
    QByteArray name = fm_file_info_get_name(file);
    QModelIndex index = indexes.first();
    if(toggled) { // remember to current custom position
      QRect itemRect = listView_->rectForIndex(index);
      customItemPos_[name] = itemRect.topLeft();
      saveItemPositions();
    }
    else { // cancel custom position and perform relayout
      QHash<QByteArray, QPoint>::iterator it = customItemPos_.find(name);
      if(it != customItemPos_.end()) {
        customItemPos_.erase(it);
        saveItemPositions();
        relayoutItems();
      }
    }
  }
}
Example #7
0
static gboolean subdir_check_job (GIOSchedulerJob *job, GCancellable *cancellable, gpointer user_data)
{
    FmDirTreeModel *dir_tree_model = FM_DIR_TREE_MODEL (user_data);

    
    // Lock ----------------------------------------------------------------------------------------
    g_mutex_lock (dir_tree_model->subdir_checks_mutex);
    
    GList *item_list = (GList*) g_queue_pop_head (&dir_tree_model->subdir_checks);
    
    FmDirTreeItem *dir_tree_item = (FmDirTreeItem*) item_list->data;
    dir_tree_model->current_subdir_check = item_list;
    
    
    // If the directory is a Drive, get it's target directory...
    //gboolean is_drive = fm_file_info_is_drive (dir_tree_item->file_info);
    GFile *gfile;
    gboolean is_mountable = fm_file_info_is_mountable (dir_tree_item->file_info);
    if (is_mountable)
    {
        gfile = g_file_new_for_path (fm_file_info_get_target (dir_tree_item->file_info));
    }
    else
    {
        gfile = fm_path_to_gfile (fm_file_info_get_path (dir_tree_item->file_info));
    }
    
    g_mutex_unlock (dir_tree_model->subdir_checks_mutex);
    // Unlock --------------------------------------------------------------------------------------
    
    //~ GError *gerror = NULL;
    //~ gfile_info = g_file_query_info (gfile, gfile_info_query_attribs, 0, fm_job_get_cancellable (fmjob), &gerror);
    
    /**
     * Parse input directory...
     * 
     */
    char *directory = fm_file_info_get_name (dir_tree_item->file_info);
    JOB_DEBUG ("\n----------------------------------------------------------------------------------------------\n");
    JOB_DEBUG ("JOB_DEBUG: subdir_check_job: check \"%s\"\n", directory);
    JOB_DEBUG ("----------------------------------------------------------------------------------------------\n");
	if (is_mountable)
    {
        JOB_DEBUG ("JOB_DEBUG: subdir_check_job: %s is mountable type !!!\n\n", directory);
    }
    
    
    GFileEnumerator *enumerator = g_file_enumerate_children (gfile,
                                                             G_FILE_ATTRIBUTE_STANDARD_NAME","
                                                             G_FILE_ATTRIBUTE_STANDARD_TYPE","
                                                             G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
                                                             0, cancellable, NULL);
    
    gboolean has_subdir = FALSE;
    if (enumerator)
    {
        while (!g_cancellable_is_cancelled (cancellable))
        {
            GFileInfo *gfile_info = g_file_enumerator_next_file (enumerator, cancellable, NULL);
            if (G_LIKELY (gfile_info))
            {
                GFileType g_file_type = g_file_info_get_file_type (gfile_info);
                gboolean is_hidden = g_file_info_get_is_hidden (gfile_info);
                
                //~ TREEVIEW_DEBUG ("TREEVIEW_DEBUG: subdir_check_job: GFileInfo for %s = %d\n",
                                //~ g_file_info_get_name (gfile_info), g_file_type);
                
                g_object_unref (gfile_info);
                
                if (g_file_type == G_FILE_TYPE_DIRECTORY || g_file_type == G_FILE_TYPE_MOUNTABLE)
                {
                    if (dir_tree_model->show_hidden || !is_hidden)
                    {
                        JOB_DEBUG ("JOB_DEBUG: subdir_check_job: A directory found in \"%s\" !!!\n\n", directory);
                        has_subdir = TRUE;
                        break;
                    }
                }
            }
            else
            {
                break;
            }
        }
        
        GError *error = NULL;
        g_file_enumerator_close (enumerator, cancellable, &error);
        g_object_unref (enumerator);
    }
    else
    {
        JOB_DEBUG ("JOB_DEBUG: subdir_check_job: Error: can't read \"%s\"...\n", directory);
    }
    
    // NO_DEBUG ("check result - %s has_dir: %d\n", g_file_get_parse_name (gfile), has_subdir);
    g_object_unref (gfile);
    
    if (!has_subdir)
    {
        JOB_DEBUG ("JOB_DEBUG: subdir_check_job: No directory found in \"%s\"\n\t\t\t  > Remove place holder\n\n",
                   directory);
        
        return g_io_scheduler_job_send_to_mainloop (job,
                                                    (GSourceFunc) subdir_check_remove_place_holder,
                                                    dir_tree_model, NULL);
    }
    
    return subdir_check_finish (dir_tree_model);
}
Example #8
0
// QListView does item layout in a very inflexible way, so let's do our custom layout again.
// FIXME: this is very inefficient, but due to the design flaw of QListView, this is currently the only workaround.
void DesktopWindow::relayoutItems() {
  loadItemPositions(); // something may have changed
  // qDebug("relayoutItems()");
  if(relayoutTimer_) {
    // this slot might be called from the timer, so we cannot delete it directly here.
    relayoutTimer_->deleteLater();
    relayoutTimer_ = NULL;
  }

  QDesktopWidget* desktop = qApp->desktop();
  int screen = 0;
  int row = 0;
  int rowCount = proxyModel_->rowCount();
  for(;;) {
    if(desktop->isVirtualDesktop()) {
      if(screen >= desktop->numScreens())
        break;
    }else {
      screen = screenNum_;
    }
    QRect workArea = desktop->availableGeometry(screen);
    workArea.adjust(12, 12, -12, -12); // add a 12 pixel margin to the work area
    // qDebug() << "workArea" << screen <<  workArea;
    // FIXME: we use an internal class declared in a private header here, which is pretty bad.
    QSize grid = listView_->gridSize();
    QPoint pos = workArea.topLeft();
    for(; row < rowCount; ++row) {
      QModelIndex index = proxyModel_->index(row, 0);
      int itemWidth = delegate_->sizeHint(listView_->getViewOptions(), index).width();
      FmFileInfo* file = proxyModel_->fileInfoFromIndex(index);
      QByteArray name = fm_file_info_get_name(file);
      QHash<QByteArray, QPoint>::iterator it = customItemPos_.find(name);
      if(it != customItemPos_.end()) { // the item has a custom position
        QPoint customPos = *it;
        // center the contents vertically
        listView_->setPositionForIndex(customPos + QPoint((grid.width() - itemWidth) / 2, 0), index);
        // qDebug() << "set custom pos:" << name << row << index << customPos;
        continue;
      }
      // check if the current pos is alredy occupied by a custom item
      bool used = false;
      for(it = customItemPos_.begin(); it != customItemPos_.end(); ++it) {
        QPoint customPos = *it;
        if(QRect(customPos, grid).contains(pos)) {
          used = true;
          break;
        }
      }
      if(used) { // go to next pos
        --row;
      }
      else {
        // center the contents vertically
        listView_->setPositionForIndex(pos + QPoint((grid.width() - itemWidth) / 2, 0), index);
        // qDebug() << "set pos" << name << row << index << pos;
      }
      // move to next cell in the column
      pos.setY(pos.y() + grid.height() + listView_->spacing());
      if(pos.y() + grid.height() > workArea.bottom() + 1) {
        // 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.setY(workArea.top());

        // check if the new column exceeds the right margin of work area
        if(pos.x() + grid.width() > workArea.right() + 1) {
          if(desktop->isVirtualDesktop()) {
            // in virtual desktop mode, go to next screen
            ++screen;
            break;
          }
        }
      }
    }
    if(row >= rowCount)
      break;
  }
}