现在的位置: 首页 > 综合 > 正文

(转)4.4 实现Edit菜单

2013年03月26日 ⁄ 综合 ⁄ 共 4133字 ⁄ 字号 评论关闭
现在我们开始实现菜单Edit相应的槽函数。
void Spreadsheet::cut()
{
    copy();
    del();
}
槽函数cut()相应Edit|Cut菜单,这里调用了两个函数,因为剪切的操作和拷贝然后删除是等价的
void Spreadsheet::copy()
{
    QTableWidgetSelectionRange range 
= selectedRange();
    QString str;
    
for (int i = 0; i < range.rowCount(); ++i) {
        
if (i > 0)
            str 
+= " ";
        
for (int j = 0; j < range.columnCount(); ++j) {
            
if (j > 0)
                str 
+= " ";
            str 
+= formula(range.topRow() + i, range.leftColumn() + j);
        }
    }
    QApplication::clipboard()
->setText(str);
}
QTableWidgetSelectionRange Spreadsheet::selectedRange() 
const
{
    QList
<QTableWidgetSelectionRange> ranges = selectedRanges();
    
if (ranges.isEmpty())
        
return QTableWidgetSelectionRange();
    
return ranges.first();
}
 槽copy()对应Edit|Copy菜单。遍历当前的选择项(如果没有明确选择,返回当前单元格),然后把选择项的公式按顺序记录下来,加到QString中,。行之间用换行符隔开,同一行中每一列之间用TAB隔开。

 

  调用静态函数QApplication::clipboard()可以得到系统的剪贴板。调用QClipboard::setText()把文本放到剪贴板上,这样该应用程序和其他支持素文本的Qt程序就可以使用这些文本。用换行符和tab的形式把行列分开也被许多应用程序支持。

QTableWidget::selectedRanges()返回所有的选择范围列表。在Spreadsheet构造函数中我们设置了选择模式为QAbstractItemView::contiguousSelection,因此选择范围只能有一个。为了程序使用方便,定义了selectedRange()函数返回当前的选择范围。
如果有选择范围,则返回第一个且也是唯一的一个选择范围。如果没有明确选择范围,则当前的单元格为一个选择(由于ContiguousSelection选择模式)。但是为了程序中可能出现的bug,也处理了选择为空的情况。
 
void Spreadsheet::paste()
{
    QTableWidgetSelectionRange range 
= selectedRange();
    QString str 
= QApplication::clipboard()->text();
    QStringList rows 
= str.split(' ');
    
int numRows = rows.count();
    
int numColumns = rows.first().count(' '+ 1;
    
if (range.rowCount() * range.columnCount() != 1
            
&& (range.rowCount() != numRows
                
|| range.columnCount() != numColumns)) {
        QMessageBox::information(
this, tr("Spreadsheet"),
                tr(
"The information cannot be pasted because the copy "
                   
"and paste areas aren't the same size."));
        
return;
    }
    
for (int i = 0; i < numRows; ++i) {
        QStringList columns 
= rows[i].split(' ');
        
for (int j = 0; j < numColumns; ++j) {
            
int row = range.topRow() + i;
            
int column = range.leftColumn() + j;
            
if (row < RowCount && column < ColumnCount)
                setFormula(row, column, columns[j]);
        }
    }
    somethingChanged();
}
菜单Edit|Paste的槽函数为paste()。我们首先得到剪贴板里的文本,然后调用静态函数QString::split()按行把文本分成QStringList。每一行为一个字符串。
接着我们确定拷贝区域的维度。行数为QStringList里QString的个数。列数为第一行中tab的个数加一。如果只有一个单元格被选中,我们使用左上角的那个粘贴区域,否则使用当前选择范围为粘贴区域。
粘贴文本时,遍历行,再一次调用QString::split()把一行文本分裂为每一列文本的组合。
 
 
 

void Spreadsheet::del()
{
    foreach (QTableWidgetItem *item, selectedItems())
        delete item;
}
槽del()对应菜单Edit|Delete。它通过删除表格里选定的Cell对象清除单元格。QTableWidget发现QTableWidgetItem被删除后会自动重新绘制所有可见区域。删除单元格后,如果调用该处的cell(),将会返回一个空指针。
void Spreadsheet::selectCurrentRow()
{
    selectRow(currentRow());
}
void Spreadsheet::selectCurrentColumn()
{
    selectColumn(currentColumn());
}
以上两个函数分别对应菜单Edit|Select|Row和Edit|Select|Column。通过调用QTableWidget::selectRow()和QTableWidget::selectColumn()实现。我们不需要实现Edit|Select|All菜单操作,这由QTableWidget继承来的QAbstractItemView::selectAll()实现的。
void Spreadsheet::findNext(const QString &str, Qt::CaseSensitivity cs)
{
    int row = currentRow();
    int column = currentColumn() + 1;
    while (row < RowCount) {
        while (column < ColumnCount) {
            if (text(row, column).contains(str, cs)) {
                clearSelection();
                setCurrentCell(row, column);
                activateWindow();
                return;
            }
            ++column;
        }
        column = 0;
        ++row;
    }
    QApplication::beep();
}
槽findNext()从当前单元格开始向右查找,查找完当前行后向下一行再继续查找,直到发现匹配的文本或到最后单元格为止。如果发现了一个匹配,清除当前选择,把匹配的单元格做为当前单元格,并把相应的窗口激活。如果没有发现匹配,则程序鸣叫,说明查找完成但没有成功找到匹配的单元格。
void Spreadsheet::findPrevious(const QString &str,
                               Qt::CaseSensitivity cs)
{
    int row = currentRow();
    int column = currentColumn() - 1;
    while (row >= 0) {
        while (column >= 0) {
            if (text(row, column).contains(str, cs)) {
                clearSelection();
                setCurrentCell(row, column);
                activateWindow();
                return;
            }
            --column;
        }
        column = ColumnCount - 1;
        --row;
    }
    QApplication::beep();
}
函数findPrevious()和findNext()很相似,只是搜索顺序是向前向上的,在A1停止。

抱歉!评论已关闭.