Files
mediasystem/ClippingStation/clippingstation.cpp
T
Mo Elzubeir 99581bc990 Major port Qt4 to Qt6
- Updated header inclusions from QtGui to QtWidgets for consistency and compatibility with Qt 5 and later.
- Replaced deprecated QApplication::desktop() with QApplication::primaryScreen() for obtaining screen DPI.
- Modified MyOutputHandler to use QMessageLogContext and QString for improved logging.
- Changed QMatrix to QTransform for image rotation in ImageCutout class.
- Updated various debug statements to use toLocal8Bit() instead of toAscii() for better string handling.
- Refactored several classes to use QElapsedTimer instead of QTime for performance measurement.
- Ensured all operator overloads in Section and Tag classes are marked as const for better const-correctness.
2025-10-22 23:04:56 -05:00

4223 lines
144 KiB
C++

//! \file clippingstation.cpp
/************************************************************************
* $Id: clippingstation.cpp 668 2011-05-15 11:08:10Z elzubeir $
*
* ------------
* Description:
* ------------
*
* (C) Copyright 2009-2011 ALLCONTENT. All rights reserved.
*
* -----------------
* Revision Details: (Updated by Revision Control System)
* -----------------
* $Date: 2011-05-15 15:08:10 +0400 (Sun, 15 May 2011) $
* $Author: elzubeir $
* $Revision: 668 $
* $HeadURL: file:///opt/svn/socialhose/trunk/app/ClippingStation/clippingstation.cpp $
*
*
************************************************************************/
#include <QtGui>
#include <QtConcurrentRun>
#include <QMutex>
#include <QDesktopServices>
#include <QScreen>
#include <QRegularExpression>
#include <cstdio>
using namespace std;
#include "clippingstation.h"
#include "ui_clippingstation.h"
#include "Importer/importerdialog.h"
#include "publication.h"
#include "tag.h"
#include "pushbuttondelegate.h"
#include "tagswrapper.h"
#include "imagecutout.h"
#include "drawerview.h"
#include "systemconfiguration.h"
#include "constants.h"
#include "pagetextdialog.h"
#include "wordcoordinates.h"
#include "searchpublicationlistdialog.h"
/*
TODO: if caching has been canceled by user, or by selecting a different issue while the first one has not completed caching yet!
It should be handled, not handled yet!
*/
QMutex g_clipMutex;
QString ClippingStation::m_cacheDir;
QString ClippingStation::m_address;
QString ClippingStation::m_username;
QString ClippingStation::m_password;
int ClippingStation::m_port;
QString ClippingStation::saveClipImagesToFtpServerErrorMsg;
QImage ClippingStation::m_thumbnail;
QSqlDatabase ClippingStation::m_ocrDatabase;
QSqlDatabase ClippingStation::m_clipDatabase;
ClippingStation::ClippingStation(QWidget *parent)
: QMainWindow(parent), ui(new Ui::ClippingStation),
m_imageCachingDialog(this, m_cachedImages)
{
if ( !readSettings()) //if you cant read settings, exit
exit(0);
if( !connectToDatabase() ) //if cant connect to database, exit
exit(0);
if ( !authenticate() ) //if cant authenticate, exit
exit(0);
ui->setupUi(this); //else, create the UI
if( m_debug.compare("on", Qt::CaseInsensitive) == 0 )
{
g_logfile.open("clippingstation.log", ios::app);
g_logfile << std::string(80, '=') << std::endl;
g_debug = true;
}
else
g_debug = false;
//create the actions
createActions();
if( m_preclip.compare("on", Qt::CaseInsensitive) == 0 )
{
m_preclipContextMenu = new QMenu(this);
m_preclipContextMenu->addAction(ui->actionModifyPreclip);
m_preclipContextMenu->addSeparator();
m_preclipContextMenu->addAction(ui->actionDeletePreclip);
}
else
{
ui->preclipButton->setEnabled(false);
ui->cancelModifyPreclipButton->setEnabled(false);
}
m_clipContextMenu = new QMenu(this);
m_clipContextMenu->addAction(ui->actionViewClipText);
m_issueContextMenu = new QMenu(this);
m_issueContextMenu->addAction(ui->actionSendIssuetoORC);
m_issuePageContextMenu = new QMenu(this);
m_issuePageContextMenu->addAction(ui->actionSendPagetoORC);
m_issuePageContextMenu->addSeparator();
m_issuePageContextMenu->addAction(ui->actionViewPageText);
m_keywordsContextMenu = new QMenu(this);
m_keywordsContextMenu->addAction(ui->actionViewKeywordsSearchword);
m_keywordsContextMenu->addSeparator();
m_keywordsContextMenu->addAction(ui->actionGoToKeywordWikiPage);
m_publication.setDatabase(m_masterDatabase);
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
//populate all the publications in the publicaiton/issue drop-down list in the dock widget
QStringList list;
QSqlQuery query("SELECT id_publication, name_publication_en FROM publication", m_slaveDatabase);
while( query.next() )
{
int publicationId = query.value(0).toString().toInt();
QString publicationName = query.value(1).toString();
list << publicationName; //populate list with values from the database
m_publicationHash[publicationName] = publicationId; //also populate the hash table with name/id values
}
//load keywords from database and add them to searchPublicationdialog
QStringList keywords;
query.exec( "SELECT name_company FROM company WHERE date_end > NOW()" );
while( query.next() )
{
QString name = query.value(0).toString();
keywords.append(name);
}
query.exec("SELECT name_searchword FROM company AS cm, searchword AS sw WHERE sw.id_company = cm.id_company AND cm.date_end > NOW() ");
while( query.next() )
{
QString name = query.value(0).toString();
keywords.append(name);
}
keywords.sort();
keywords.removeDuplicates();
m_searchPublicationsDlg.setKeywords(keywords);
query.exec("SELECT id_country, name_country_en FROM country");
while( query.next() )
{
int id = query.value(0).toString().toInt();
QString name = query.value(1).toString();
m_countriesHash[name] = id; //also populate the hash table with name/id values
}
QList<QString> clist = m_countriesHash.keys();
QStringList strlist;
for(int i=0; i < clist.count(); i++)
strlist.append(clist[i]);
m_searchPublicationsDlg.setCountryList( strlist );
QCompleter* completer = new QCompleter(list, this); //createa completer with the list of publication names
completer->setCaseSensitivity(Qt::CaseInsensitive);
ui->publicationNameLineEdit_2->setCompleter(completer); //use the complete with the publicationLineEdit
// should use QDir's homePath to get the path and then use .socialhose/cache as the directory within the homePath
QDir homeDir("/home");
#if defined Q_WS_X11
m_cacheDir = homeDir.homePath() + "/.socialhose/cache/";
#elif defined Q_WS_MACX
m_cacheDir = homeDir.homePath() + "/.socialhose/cache/";
#else
m_cacheDir = QApplication::applicationDirPath();
if(!m_cacheDir.endsWith("/"))
m_cacheDir += "/";
m_cacheDir += "cache/";
#endif
ui->fullpageView->setClippingStation(this);
ui->statusBar->addProgressBarWidget(&m_imageCachingDialog);
ImporterDialog *dlg = new ImporterDialog(this, m_masterDatabase, m_slaveDatabase, m_user); //create the importer dialog
ui->importerDockWidget->setWidget(dlg); //and insert it to the importer dock widget
tabifyDockWidget(ui->importerDockWidget, ui->publicatonIssueDockWidget);
ui->importerDockWidget ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
ui->publicatonIssueDockWidget ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
ui->importerDockWidget ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
//ui->importerDockWidget->raise();
SystemConfiguration::retreiveSystemConfiguration(m_slaveDatabase);
m_tagsWrapper.set(ui->treeView, ui->treeWidget, ui->keywordLineEdit);
ui->stackedDrawerViewWidget->removeWidget(ui->stackedDrawerViewWidget->widget(0) ); //remove the first page from the stak
m_currentA4Scale = 1.0;
drawerAddPage(true);
m_runningMode = NORMAL_MODE;
m_filterMode = NO_FILTER;
m_currentPreclipId = 0;
m_firstPageInClip = ""; //reset it
m_imageIndex = m_preclippedImageIndex = m_clippedImageIndex = 0;
m_imageModelIndex = m_preclippedImageModelIndex = m_clippedImageModelIndex = QModelIndex();
showMaximized();
ui->cancelModifyPreclipButton->setVisible(false);
//install filter to track mouse
ui->fullpageView->installEventFilter(this);
connect(&m_saveClipImagesToFtpServerWatcher, SIGNAL(finished() ), this, SLOT( saveClipImagesToFtpServerWatcherFinished() ) ); //this signal is used to upload clips to ftp server
connect(&m_saveClipImagesToFileServerWatcher, SIGNAL(finished() ), this, SLOT( saveClipImagesToFileServerWatcherFinished() ) ); //this signal is used to upload clips to ftp server
connect(&m_addTextToClipWatcher, SIGNAL(finished()), this, SLOT(addTextToClipWatcherFinished()));
//set shortcuts
setShortcuts();
connect(&m_trackingTimer, SIGNAL(timeout()), this, SLOT(updateTrackLabel()));
m_trackingTimer.setInterval(1000);
m_trackingSeconds = 0;
m_currentPageId = 0;
m_isPaused = false;
}
ClippingStation::~ClippingStation()
{
//qDebug("~ClippingStation()");
delete ui;
unlockImages();
m_trackingTimer.stop();
if(m_currentPageId > 0 && m_trackingSeconds > 0)
m_user.updateTrack(m_currentPageId, m_trackingSeconds);
m_masterDatabase.close();
m_slaveDatabase.close();
//delete all the files on the tmp directory
//QDir dir(m_cacheDir);
//recursiveDelete( dir );
//qDebug("end of ~ClippingStation()");
}
bool ClippingStation::readSettings()
{
#ifdef Q_WS_X11
QString config = "/etc/socialhose.ini";
#elif defined (Q_WS_MACX)
QString config = "/etc/socialhose.ini";
#else
QString config = QApplication::applicationDirPath()+ "/config.ini";
#endif
QSettings settings(config, QSettings::IniFormat);
m_masterDatabaseHost = settings.value("master database/server").toString(); //read master database's server value from settings
m_masterDatabaseName = settings.value("master database/database").toString(); //read master database's database name value from settings
m_masterDatabaseUser = settings.value("master database/uid").toString(); //read master database's user id value from settings
m_masterDatabasePassword = settings.value("master database/pwd").toString(); //read master database's password value from settings
m_masterDatabasePort = settings.value("master database/port").toInt(); //read master database's port value from settings
// if any string is empty return false, else return true
if(m_masterDatabaseName.isEmpty() || m_masterDatabaseHost.isEmpty() || m_masterDatabaseUser.isEmpty() ||
m_masterDatabasePassword.isEmpty() || ( m_masterDatabasePort == 0) )
{
QMessageBox::critical(this, tr("config error"), tr("Error reading 'config.ini' master database configurations\nMake sure the file exists, and its properly formatted!"));
return false;
}
m_slaveDatabaseHost = settings.value("slave database/server").toString();
m_slaveDatabaseName = settings.value("slave database/database").toString();
m_slaveDatabaseUser = settings.value("slave database/uid").toString();
m_slaveDatabasePassword = settings.value("slave database/pwd").toString();
m_slaveDatabasePort = settings.value("slave database/port").toInt();
// if any string is empty return false, else return true
if(m_slaveDatabaseName.isEmpty() || m_slaveDatabaseHost.isEmpty() || m_slaveDatabaseUser.isEmpty() ||
m_slaveDatabasePassword.isEmpty() || ( m_slaveDatabasePort == 0) )
{
QMessageBox::critical(this, tr("config error"), tr("Error reading 'config.ini' slave database configurations\nMake sure the file exists, and its properly formatted!"));
return false;
}
m_ocrDatabaseHost = settings.value("ocr database/server").toString();
m_ocrDatabaseName = settings.value("ocr database/database").toString();
m_ocrDatabaseUser = settings.value("ocr database/uid").toString();
m_ocrDatabasePassword = settings.value("ocr database/pwd").toString();
m_ocrDatabasePort = settings.value("ocr database/port").toInt();
m_useFtp = settings.value("ftp access/useftp").toInt(); //if its set to 0, its false, otherwise it true
if(m_useFtp)
{
m_address = settings.value("ftp access/server").toString();
m_username = settings.value("ftp access/username").toString();
m_password = settings.value("ftp access/password").toString();
m_port = settings.value("ftp access/port").toInt();
if(m_address.isEmpty() || m_username.isEmpty() || m_password.isEmpty() || (m_port == 0))
{
QMessageBox::critical(this, tr("config error"), tr("Error reading 'config.ini' Ftp server configurations\nMake sure the file is properly formatted!"));
return false;
}
}
//read shortcuts
m_clipShortcut = settings.value("shortcuts/Clip").toString();
m_preclipShortcut = settings.value("shortcuts/Preclip").toString();
m_addPageShortcut = settings.value("shortcuts/AddPage").toString();
m_nextPageShortcut = settings.value("shortcuts/NextPage").toString();
m_previousPageShortcut = settings.value("shortcuts/PreviousPage").toString();
m_debug = settings.value("debug mode/debug").toString();
m_preclip = settings.value("preclip mode/preclip", "on").toString();
m_maxTimeLimit = settings.value("time limit/limit").toInt();
return true;
}
bool ClippingStation::connectToDatabase()
{
// add a connection to databse based on the mysql driver, and name it master
m_masterDatabase = QSqlDatabase::addDatabase("QMYSQL", "master_123");
// initalize the connection
m_masterDatabase.setHostName(m_masterDatabaseHost);
m_masterDatabase.setPort(m_masterDatabasePort);
m_masterDatabase.setDatabaseName(m_masterDatabaseName);
m_masterDatabase.setUserName(m_masterDatabaseUser);
m_masterDatabase.setPassword(m_masterDatabasePassword);
// try to open the connection, if ok returns true, else returns false
bool ok = m_masterDatabase.open();
if(!ok)
{
// if error, get the error from the database text and print it to debug screen
QString str = m_masterDatabase.lastError().databaseText();
QMessageBox::critical(this, tr("Database Error"), tr("Error connecting to master database\n") + str);
return false;
}
// add a connection to databse based on the mysql driver, and name it slave
m_slaveDatabase = QSqlDatabase::addDatabase("QMYSQL", "slave");
// initalize the connection
m_slaveDatabase.setHostName(m_slaveDatabaseHost);
m_slaveDatabase.setPort(m_slaveDatabasePort);
m_slaveDatabase.setDatabaseName(m_slaveDatabaseName);
m_slaveDatabase.setUserName(m_slaveDatabaseUser);
m_slaveDatabase.setPassword(m_slaveDatabasePassword);
// try to open the connection, if ok returns true, else returns false
ok = m_slaveDatabase.open();
if(!ok)
{
// if error, get the error from the database text and print it to debug screen
QString str = m_slaveDatabase.lastError().databaseText();
QMessageBox::critical(this, tr("Database Error"), tr("Error connecting to slave database\n") + str);
return false;
}
m_ocrDatabase = QSqlDatabase::addDatabase("QMYSQL", "ocr");
// initalize the connection
m_ocrDatabase.setHostName(m_ocrDatabaseHost);
m_ocrDatabase.setPort(m_ocrDatabasePort);
m_ocrDatabase.setDatabaseName(m_ocrDatabaseName);
m_ocrDatabase.setUserName(m_ocrDatabaseUser);
m_ocrDatabase.setPassword(m_ocrDatabasePassword);
// try to open the connection, if ok returns true, else returns false
ok = m_ocrDatabase.open();
if(!ok)
{
// if error, get the error from the database text and print it to debug screen
QString str = m_ocrDatabase.lastError().databaseText();
QMessageBox::critical(this, tr("Database Error"), tr("Error connecting to ocr database\n") + str);
return false;
}
m_clipDatabase = m_masterDatabase.cloneDatabase(m_masterDatabase, "clip");
m_clipDatabase.open();
if(!m_clipDatabase.isOpen())
{
QString str = m_clipDatabase.lastError().text();
QMessageBox::critical(this, tr("Database Error"), tr("Error opening clip database\n") + str);
return false;
}
return true;
}
bool ClippingStation::authenticate()
{
//after opening the database connection, we pass it to the user object
m_user.setSlaveDatabase(m_slaveDatabase);
m_user.setMasterDatabase(m_masterDatabase);
return m_user.authenticate();
}
void ClippingStation::createActions()
{
//create actions for the main window
connect(ui->actionImporter, SIGNAL(triggered()), this, SLOT(onActionImporter()));
connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close()));
connect(ui->actionKeyword, SIGNAL(triggered()), this, SLOT(onActionKeyword()));
connect(ui->actionPublications, SIGNAL(triggered()), this, SLOT(onActionPublications()));
connect(ui->actionClip, SIGNAL(triggered()), this, SLOT(onActionClip()));
if( m_preclip.compare("on", Qt::CaseInsensitive) == 0 )
{
connect(ui->actionPreclip, SIGNAL(triggered()), this, SLOT(onActionPreclip()));
connect(ui->actionModifyPreclip, SIGNAL(triggered()), this, SLOT(onActionModifyePreclip()));
connect(ui->actionDeletePreclip, SIGNAL(triggered()), this, SLOT(onActionDeletePreclip()));
}
//drawer actions
connect(ui->actionDrawerAddPage, SIGNAL(triggered()), this, SLOT(drawerAddPage()));
connect(ui->actionDrawerRemovePage, SIGNAL(triggered()), this, SLOT(drawerRemovePage()));
//page navigation actions
connect(ui->actionFirstPage, SIGNAL(triggered()), this, SLOT(firstPage()));
connect(ui->actionPreviousPage, SIGNAL(triggered()), this, SLOT(previousPage()));
connect(ui->actionNextPage, SIGNAL(triggered()), this, SLOT(nextPage()));
connect(ui->actionLastPage, SIGNAL(triggered()), this, SLOT(lastPage()));
//zoom in/out
connect(ui->actionZoomIn, SIGNAL(triggered()), this, SLOT(zoomIn()));
connect(ui->actionZoomOut, SIGNAL(triggered()), this, SLOT(zoomOut()));
//auto-arrange
connect(ui->actionAutoArrange, SIGNAL(triggered()), this, SLOT(onActionAutoArrange()));
connect(ui->actionMarkIssueAsDone, SIGNAL(triggered()), this, SLOT(onActionMarkIssueAsDone()));
connect(ui->actionMarkIssueAsUndone,SIGNAL(triggered()), this, SLOT(onActionMarkIssueAsUndone()));
connect(ui->actionSendIssuetoORC, SIGNAL(triggered()), this, SLOT(onActionSendIssueToOCR()));
connect(ui->actionSendPagetoORC, SIGNAL(triggered()), this, SLOT(onActionSendPageToOCR()));
connect(ui->actionViewPageText, SIGNAL(triggered()), this, SLOT(onActionViewPageText()));
connect(ui->actionViewClipText, SIGNAL(triggered()), this, SLOT(onActionViewClipText()));
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onActionAbout()));
connect(ui->actionViewKeywordsSearchword, SIGNAL(triggered()), this, SLOT(onActionViewKeywordsSearchword()));
connect(ui->actionGoToKeywordWikiPage , SIGNAL(triggered()), this, SLOT(onActionGoToKeywordWikiPage()));
}
void ClippingStation::onActionImporter()
{
ui->importerDockWidget->setVisible(ui->actionImporter->isChecked());
}
void ClippingStation::onActionKeyword()
{
ui->keywordDockWidget->setVisible(ui->actionKeyword->isChecked());
}
void ClippingStation::onActionPublications()
{
ui->publicatonIssueDockWidget->setVisible(ui->actionPublications->isChecked());
}
void ClippingStation::onActionClip()
{
clip();
}
void ClippingStation::onActionPreclip()
{
preclip();
}
void ClippingStation::onActionModifyePreclip()
{
QModelIndexList list = ui->clipsTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
articleTreeViewClicked(index);
setModifyPreclipButton(true);
}
void ClippingStation::onActionDeletePreclip()
{
QModelIndexList list = ui->clipsTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
if(index.isValid())
{
//check index to the value
QAbstractItemModel *model = ui->clipsTreeView->model();
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
//if the user clicked on top level entries, just return
if ( index == preclipRootIndex ||
index == clipRootIndex )
return;
int id;
if ( index.parent() == preclipRootIndex ||
index.parent().parent() == preclipRootIndex )
{
m_runningMode = PRECLIPPING_MODE;
QModelIndex currentIndex;
m_clippedImageModelIndex = QModelIndex();
//if the selection is the Preclip(), then it will contain the id
if(index.parent() == preclipRootIndex)
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
else
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
switch( QMessageBox::question(
this,
tr("Delete Preclip"),
tr("This will delete the preclip PERMANENTLY, Are you sure?"),
QMessageBox::Yes |
QMessageBox::No,
QMessageBox::No) )
{
case QMessageBox::Yes:
break;
case QMessageBox::No:
return;
default:
return;
}
m_publication.currentIssue()->preclip(id).deleteArticle(m_masterDatabase);
m_publication.currentIssue()->deleteArticleFromView(ui->clipsTreeView, id);
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
//m_publication.currentIssue()->loadArticles(m_slaveDatabase, m_filterMode);
//m_publication.currentIssue()->showArticles(ui->clipsTreeView);
}
}
}
void ClippingStation::onActionAutoArrange()
{
QList<ImageCutout*> cutouts = ui->fullpageView->imageCutoutsList();
if(cutouts.count() <= 0)
return;
orderList(cutouts);
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget() );
QSizeF cellSize = A4CellSize(true);
bool isfirstPage = true;
bool resetArray = true;
for(int i=0; i< cutouts.count(); i++)
{
QString currentImage;
if(m_runningMode == NORMAL_MODE)
currentImage = m_localImagesList[m_imageIndex];
else if(m_runningMode == PRECLIPPING_MODE)
currentImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
else if(m_runningMode == CLIPPING_MODE)
currentImage = m_clippedLocalImagesList[m_clippedImageIndex];
if(cutouts[i]->pageName() != currentImage)
{
if(m_runningMode == NORMAL_MODE)
{
int index = m_localImagesList.indexOf(cutouts[i]->pageName());
if(index < 0)
return;
m_imageIndex = index;
}
else if(m_runningMode == PRECLIPPING_MODE)
{
int index = m_preclippedLocalImagesList.indexOf(cutouts[i]->pageName());
if(index < 0)
return;
m_preclippedImageIndex = index;
}
else if(m_runningMode == CLIPPING_MODE)
{
int index = m_clippedLocalImagesList.indexOf(cutouts[i]->pageName());
if(index < 0)
return;
m_clippedImageIndex = index;
}
loadImage();
}
QImage img = cutouts[i]->createCutout();
int type = cutouts[i]->areaType();
QPointF pos;
qreal scale = 1.0;
if(calculatePosAndScale(cellSize, img, type, resetArray, pos, scale))
{
addMargintoPos(pos, isfirstPage);
view->addCutout(img, pos, scale);
}
else
{
isfirstPage = false;
drawerAddPage(isfirstPage);
drawerNextPage();
view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget() );
cellSize = A4CellSize(isfirstPage);
if(calculatePosAndScale(cellSize, img, type, true, pos, scale))
{
addMargintoPos(pos, isfirstPage);
view->addCutout(img, pos, scale);
}
else
{
//error, the cutout is larger than the avaialble space in the A4 page
ui->stackedDrawerViewWidget->removeWidget( ui->stackedDrawerViewWidget->currentWidget() );
updateDrawerPageInformation();
QMessageBox::information(this, tr("Large Cutout"), tr("Cutout number %1 does not fit in the available space").arg(i+1));
return;
}
}
resetArray = false;
}
//iterate thru all the views, and center the images
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
ui->stackedDrawerViewWidget->setCurrentIndex(i);
view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
bool isArabic = (m_publication.language() == "Arabic");
view->centerCutouts(isArabic);
}
//return to the first page to create the thumbnail
QString currentImage;
if(m_runningMode == NORMAL_MODE)
currentImage = m_localImagesList[m_imageIndex];
else if(m_runningMode == PRECLIPPING_MODE)
currentImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
else if(m_runningMode == CLIPPING_MODE)
currentImage = m_clippedLocalImagesList[m_clippedImageIndex];
if(cutouts[0]->pageName() != currentImage)
{
if(m_runningMode == NORMAL_MODE)
{
int index = m_localImagesList.indexOf(cutouts[0]->pageName());
if(index < 0)
return;
m_imageIndex = index;
}
else if(m_runningMode == PRECLIPPING_MODE)
{
int index = m_preclippedLocalImagesList.indexOf(cutouts[0]->pageName());
if(index < 0)
return;
m_preclippedImageIndex = index;
}
else if(m_runningMode == CLIPPING_MODE)
{
int index = m_clippedLocalImagesList.indexOf(cutouts[0]->pageName());
if(index < 0)
return;
m_clippedImageIndex = index;
}
loadImage();
}
createThumbnail();
}
void ClippingStation::onActionMarkIssueAsDone()
{
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
//QString date =
if( !index.isValid() )
return;
switch( QMessageBox::question(
this,
tr("Mark Issue as Done"),
tr("This will mark the current issue as Done\nAre you sure?"),
QMessageBox::Yes |
QMessageBox::No,
QMessageBox::No) )
{
case QMessageBox::Yes:
break;
case QMessageBox::No:
return;
default:
return;
}
QAbstractItemModel *model = ui->issuesTreeView->model();
if(model->parent(index) == QModelIndex() ) index = index;
else if(model->parent(index).parent() == QModelIndex() ) index = index.parent();
else if(model->parent(index).parent().parent() == QModelIndex() ) index = index.parent().parent();
else index = index.parent().parent().parent();
QString date = model->data(index, Qt::DisplayRole).toString();
m_publication.issue(date)->markIssueAsDone(m_masterDatabase, true, m_user.id());
model->setData(index, QVariant(QIcon(":/icons/ok.png")) , Qt::DecorationRole);
}
void ClippingStation::onActionMarkIssueAsUndone()
{
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
//QString date =
if( !index.isValid() )
return;
switch( QMessageBox::question(
this,
tr("Mark Issue as Undone"),
tr("This will mark the current issue as Undone\nAre you sure?"),
QMessageBox::Yes |
QMessageBox::No,
QMessageBox::No) )
{
case QMessageBox::Yes:
break;
case QMessageBox::No:
return;
default:
return;
}
QAbstractItemModel *model = ui->issuesTreeView->model();
if(model->parent(index) == QModelIndex() ) index = index;
else if(model->parent(index).parent() == QModelIndex() ) index = index.parent();
else if(model->parent(index).parent().parent() == QModelIndex() ) index = index.parent().parent();
else index = index.parent().parent().parent();
QString date = model->data(index, Qt::DisplayRole).toString();
m_publication.issue(date)->markIssueAsDone(m_masterDatabase, false, m_user.id());
model->setData(index, QVariant(QIcon(":/icons/cancel.png")) , Qt::DecorationRole);
}
void ClippingStation::onActionSendPageToOCR()
{
QAbstractItemModel *model = ui->issuesTreeView->model();
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
QString pageName = index .data(Qt::DisplayRole).toString();
//convert pageName from Page # to ####.jpg
pageName = QString("%1.jpg").arg(pageName.remove(QRegularExpression("[^\\d]")), 4, QChar('0'));
QString sectionName = model->parent(index) .data(Qt::DisplayRole).toString();
QString issueDate = model->parent(index).parent().data(Qt::DisplayRole).toString();
//send the page to OCR to be processed again
QSqlQuery query(m_slaveDatabase);
query.prepare("SELECT id_publication_issue FROM publication_issue "
"WHERE id_publication = :id_publication AND id_issue = :id_issue AND issue_date = :issue_date");
query.bindValue(":id_publication", m_publication.id() );
query.bindValue(":id_issue", m_publication.issue(issueDate)->id() );
query.bindValue(":issue_date", issueDate);
if(!query.exec())
{
//error happened
return;
}
int id_publication_issue = 0;
if(query.next())
{
id_publication_issue = query.value(0).toInt();
//return id_publication_issue;
//break;
}
query.prepare("SELECT id_issue_sections FROM issue_sections WHERE "
"id_publication_issue = :id_publication_issue AND id_section = :id_section");
query.bindValue(":id_publication_issue", id_publication_issue);
query.bindValue(":id_section", m_publication.issue(issueDate)->section(sectionName).id() );
if ( !query.exec() )
return;
int id_issue_sections = 0;
if( query.next() )
{
id_issue_sections = query.value(0).toInt();
//break;
}
//we have the page name, and the id_issue_sections, we can now reset the pages to OCR
//query.exec("LOCK TABLES section_pages WRITE, page_text WRITE, page_tag_coordinates WRITE;"); //query.exec("LOCK TABLES section_pages");
//first remove the pre processed values
query.prepare("SELECT section_pages FROM section_pages "
"WHERE "
" id_issue_sections = :id_issue_sections "
" AND page_name like :page_name");
query.bindValue(":id_issue_sections" , id_issue_sections);
query.bindValue(":page_name", pageName);
if (query.exec() )
{
int id = 0;
if(query.next())
id = query.value(0).toInt();
//delete the previous coordinates
query.prepare("DELETE FROM page_tag_coordinates WHERE id_section_pages = :id");
query.bindValue(":id", id);
query.exec();
query.prepare("DELETE FROM page_text WHERE id_section_pages = :id");
query.bindValue(":id", id);
query.exec();
}
query.prepare("UPDATE section_pages SET status = 1 "
"WHERE "
" section_pages.id_issue_sections = :id_issue_sections "
" AND section_pages.page_name like :page_name AND status != 1");
query.bindValue(":id_issue_sections" , id_issue_sections);
query.bindValue(":page_name", pageName);
query.exec();
//query.exec("UNLOCK TABLES");
model->setData(index, QVariant(QIcon(":/icons/gray_circle.png")) , Qt::DecorationRole);
//loadImage(); //no need to re-load the page because it may not by the page that the user is currently looking at
}
void ClippingStation::onActionSendIssueToOCR()
{
switch( QMessageBox::question(
this,
tr("Send issue back to OCR"),
tr("This operation will send the entire issue back to OCR\nAre you sure?"),
QMessageBox::Yes |
QMessageBox::No,
QMessageBox::No) )
{
case QMessageBox::Yes:
break;
case QMessageBox::No:
return;
default:
return;
}
QAbstractItemModel *model = ui->issuesTreeView->model();
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex issueIndex = list[0];
QString issueDate = model->data(issueIndex, Qt::DisplayRole).toString();
//send the entire issue to OCR to be processed again
QSqlQuery query(m_slaveDatabase);
query.exec("LOCK TABLES section_pages WRITE, issue_sections READ , publication_issue READ;");
//first remove the pre processed values
query.prepare("UPDATE section_pages, issue_sections, publication_issue "
" SET status = 1 "
" WHERE section_pages.id_issue_sections = issue_sections.id_issue_sections "
" AND issue_sections.id_publication_issue = publication_issue.id_publication_issue "
" AND id_issue = :id_issue AND publication_issue.id_publication = :id_publication;");
query.bindValue(":id_issue" , m_publication.issue(issueDate)->id() );
query.bindValue(":id_publication", m_publication.id() );
if ( !query.exec() )
{
query.exec("UNLOCK TABLES");
return;
}
query.exec("UNLOCK TABLES");
//////////////////////////////////////////////////////////////
int sectionsCount = model->rowCount(issueIndex);
for(int j=0; j < sectionsCount; j++)
{
QString sectionName = model->index(j, 0, issueIndex).data(Qt::DisplayRole).toString();
QModelIndex sectionIndex = model->index(j, 0, issueIndex);
int pagesCount = model->rowCount(sectionIndex);
for(int k=0; k< pagesCount; k++)
{
QModelIndex pageIndex = model->index(k, 0, sectionIndex);
model->setData(pageIndex, QVariant(QIcon(":/icons/gray_circle.png")) , Qt::DecorationRole);
}
}
}
void ClippingStation::onActionViewClipText()
{
QAbstractItemModel *model = ui->clipsTreeView->model();
QModelIndexList list = ui->clipsTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
//if the user clicked on top level entries, just return
int id;
if ( index.parent() == clipRootIndex ||
index.parent().parent() == clipRootIndex )
{
//m_clippedImageModelIndex = QModelIndex();
if(index.parent() == clipRootIndex)
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
else
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
//get the text_ocr.
QSqlQuery query(m_masterDatabase);
query.prepare("SELECT `text_ocr` FROM article WHERE id_article = :id");
query.bindValue(":id", id);
if ( !query.exec() )
return;
QString text;
while(query.next())
text = query.value(0).toString();
PageTextDialog dlg(this, text);
dlg.exec();
}
}
void ClippingStation::onActionViewPageText()
{
QAbstractItemModel *model = ui->issuesTreeView->model();
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
QString pageName = index .data(Qt::DisplayRole).toString();
pageName = QString("%1.jpg").arg(pageName.remove(QRegularExpression("[^\\d]")), 4, QChar('0'));
QString sectionName = model->parent(index) .data(Qt::DisplayRole).toString();
QString issueDate = model->parent(index).parent().data(Qt::DisplayRole).toString();
QSqlQuery query(m_slaveDatabase);
query.prepare("SELECT id_publication_issue FROM publication_issue "
"WHERE id_publication = :id_publication AND id_issue = :id_issue AND issue_date = :issue_date");
query.bindValue(":id_publication", m_publication.id() );
query.bindValue(":id_issue", m_publication.issue(issueDate)->id() );
query.bindValue(":issue_date", issueDate);
if(!query.exec())
{
//error happened
return;
}
int id_publication_issue = 0;
if(query.next())
id_publication_issue = query.value(0).toInt();
query.prepare("SELECT id_issue_sections FROM issue_sections WHERE "
"id_publication_issue = :id_publication_issue AND id_section = :id_section");
query.bindValue(":id_publication_issue", id_publication_issue);
query.bindValue(":id_section", m_publication.issue(issueDate)->section(sectionName).id() );
if ( !query.exec() )
return;
int id_issue_sections = 0;
if( query.next() )
id_issue_sections = query.value(0).toInt();
query.exec("LOCK TABLES section_pages READ");
query.prepare("SELECT section_pages FROM section_pages "
"WHERE "
" section_pages.id_issue_sections = :id_issue_sections "
" AND section_pages.page_name like :page_name");
query.bindValue(":id_issue_sections" , id_issue_sections);
query.bindValue(":page_name", pageName);
if ( !query.exec() )
{
query.exec("UNLOCK TABLES");
return;
}
int id = 0;
while(query.next())
id = query.value(0).toInt();
query.exec("UNLOCK TABLES");
query.prepare("SELECT `text` FROM page_text WHERE id_section_pages = :id");
query.bindValue(":id", id);
if ( !query.exec() )
return;
QString text;
while(query.next())
text = query.value(0).toString();
PageTextDialog dlg(this, text);
dlg.exec();
}
void ClippingStation::onActionViewKeywordsSearchword()
{
// QAbstractItemModel *model = ui->treeView->model();
QModelIndexList list = ui->treeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
QString pageName = index .data(Qt::DisplayRole).toString();
//get searchwords for this keywords
QString lstring = Tag::loadSearchwords(m_slaveDatabase, pageName);
QMessageBox::information(0, "Searchwords", QString("Searchwords are:\n%1").arg(lstring));
}
void ClippingStation::onActionGoToKeywordWikiPage()
{
// QAbstractItemModel *model = ui->treeView->model();
QModelIndexList list = ui->treeView->selectionModel()->selectedIndexes();
if (list.count() == 0)
return;
QModelIndex index = list[0];
QString keyword = index.data(Qt::DisplayRole).toString();
keyword.replace(QRegularExpression("\\s"), "_");
keyword.replace(' ', '_');
// keyword.replace("'", "_");
// keyword.replace("-", "_");
QUrl url(QString("%1%2").arg(SystemConfiguration::wikiUrl()).arg(keyword));
// QMessageBox::information(this, "test", QString("URL is %1").arg(url.toString()));
QDesktopServices::openUrl (url);
}
void ClippingStation::onActionAbout()
{
QMessageBox::about(this, tr("About Clipping Station"),
"<html><body><p style=""color: #696969""><b>Clipping Station</b> - $Revision: 668 $</p>"
"<p style=""color: #696969"">(c) Copyright 2009-2011 ALLCONTENT. All rights reserved.</p></body></html>");
}
bool ClippingStation::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->treeWidget)
{
if(event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if(keyEvent->key() == Qt::Key_Enter)
{
selectKeyword();
return true;
}
}
}
return QMainWindow::eventFilter(obj, event);
}
void ClippingStation::loadIssues()
{
QString name = ui->publicationNameLineEdit_2->text();
int id = m_publicationHash[name];
m_publication.setId(id);
m_publication.setName(name);
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
//m_publication.loadIssues(ui->issuesTreeView, m_cacheDir);
m_publication.loadIssuesOnly(ui->issuesTreeView);
//m_publication.addImageCutoutsToIssues(ui->issuesTreeView, true);
m_currentIssueDate = "";
m_currentSectionName="";
}
void ClippingStation::loadIssuesWithPreclipsOnly()
{
clock_t start = clock();
QString name = ui->preclippedPublicationComboBox->currentText();
if ( name.isEmpty() )
return;
int id = m_publicationHash[name];
m_publication.setId(id);
m_publication.setName(name);
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
m_publication.loadIssuesWithPreclipsOnly(ui->issuesTreeView, m_cacheDir);
m_currentIssueDate = "";
m_currentSectionName="";
QAbstractItemModel *model = ui->issuesTreeView->model();
QModelIndex issuesIndex = model->index(0, 0, QModelIndex() );
if( issuesIndex.isValid() )
{
issueTreeViewItemClicked(issuesIndex);
//load the first pre-clip
QAbstractItemModel *model = ui->clipsTreeView->model();
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
QModelIndex pindex = model->index(0, 0, preclipRootIndex);
if(pindex.isValid())
articleTreeViewClicked(pindex);
}
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("loadIssuesWithPreclipsOnly() Time: %f", diff);
}
void ClippingStation::loadFilteredIssues()
{
clock_t start = clock();
QString name = ui->filteredPublicationComboBox->currentText();
if ( name.isEmpty() )
return;
int id = m_publicationHash[name];
m_publication.setId(id);
m_publication.setName(name);
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
QString keyword, startDate, endDate, type, country, ocrSearchword, status;
bool ischecked;
m_searchPublicationsDlg.get(keyword, ischecked, startDate, endDate, type, country, ocrSearchword, status);
//now search for the publications that meet those criteria
int countryId = -1;
if(!country.isEmpty())
countryId = m_countriesHash[country];
int typeId = -1;
if(!type.isEmpty())
{
if(type.compare("newspaper", Qt::CaseInsensitive) == 0) //NEWSPAPER 1
typeId = 1;
else if(type.compare("magazine", Qt::CaseInsensitive) == 0)
typeId = 2;
}
m_publication.loadFilteredIssues(ui->issuesTreeView, m_ocrDatabase, m_cacheDir, startDate, endDate, keyword, ocrSearchword, status);
m_currentIssueDate = "";
m_currentSectionName="";
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("loadIssuesWithPreclipsOnly() Time: %f", diff);
}
void ClippingStation::loadUndoneIssuesOnly()
{
clock_t start = clock();
QString name = ui->undonePublicationComboBox->currentText();
if ( name.isEmpty() )
return;
int id = m_publicationHash[name];
m_publication.setId(id);
m_publication.setName(name);
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
m_publication.loadUndoneIssuesOnly(ui->issuesTreeView);
m_currentIssueDate = "";
m_currentSectionName="";
/*
QAbstractItemModel *model = ui->issuesTreeView->model();
QModelIndex issuesIndex = model->index(0, 0, QModelIndex() );
if( issuesIndex.isValid() )
{
issueTreeViewItemClicked(issuesIndex);
//load the first pre-clip
QAbstractItemModel *model = ui->clipsTreeView->model();
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
QModelIndex pindex = model->index(0, 0, preclipRootIndex);
if(pindex.isValid())
articleTreeViewClicked(pindex);
}
*/
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("loadUndoneIssuesOnly() Time: %f", diff);
}
void ClippingStation::issueTreeViewItemClicked(QModelIndex index)
{
qDebug("issueTreeViewItemClicked()");
if( index.isValid() )
{
QAbstractItemModel *model = ui->issuesTreeView->model();
if(model->parent(index) == QModelIndex() )
{
//qDebug("We are at Issue Level");
//we may have not loaded the sections, so we do that, and then do our work
//
QString issueDate = model->data(index , Qt::DisplayRole).toString();
if( !m_publication.issue(issueDate)->isLoaded() )
{
//load the issue, and
QStandardItemModel *standardModel = static_cast<QStandardItemModel*> ( ui->issuesTreeView->model() );
QStandardItem* issueItem = standardModel->itemFromIndex(index);
m_publication.loadIssueSections(issueItem, issueDate, m_cacheDir);
}
QString sectionName = model->data(model->index(0, 0, index), Qt::DisplayRole).toString();
if( m_currentIssueDate != issueDate)
ui->fullpageView->removeImageCutouts();
m_currentIssueDate = issueDate;
m_publication.setCurrentIssue(issueDate);
m_publication.currentIssue()->showArticlesInView(m_masterDatabase, ui->clipsTreeView, m_filterMode);
m_publication.currentIssue()->section(sectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
ui->issuesTreeView->expand(index);
updateSectionPagesStatus();
return;
}
if(model->parent(index).parent() == QModelIndex() )
{
//qDebug("We are at Section Level");
QString issueDate = model->data(index.parent(), Qt::DisplayRole).toString();
QString sectionName = model->data(index , Qt::DisplayRole).toString();
if( m_currentIssueDate != issueDate)
ui->fullpageView->removeImageCutouts();
m_currentIssueDate = issueDate;
m_publication.setCurrentIssue(issueDate);
m_publication.currentIssue()->showArticlesInView(m_masterDatabase, ui->clipsTreeView, m_filterMode);
m_publication.currentIssue()->section(sectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
ui->issuesTreeView->expand(index);
updateSectionPagesStatus();
return;
}
bool showArticleSelections;
int articleId = 0;
if(model->parent(index).parent().parent() == QModelIndex() ) //its the image
showArticleSelections = false;
else //its a selection in the image
{
showArticleSelections = true;
articleId = index.data(Qt::DisplayRole).toInt();
index = index.parent();
//gotoArticlePage(articleId);
}
QString sectionName = model->parent(index) .data(Qt::DisplayRole).toString();
QString issueDate = model->parent(index).parent().data(Qt::DisplayRole).toString();
if( m_currentIssueDate != issueDate)
{
ui->fullpageView->removeImageCutouts();
updateSectionPagesStatus();
}
else if(m_currentSectionName != sectionName)
ui->fullpageView->hideImageCutouts();
m_currentIssueDate = issueDate;
m_currentSectionName = sectionName;
m_publication.setCurrentIssue(issueDate);
m_publication.currentIssue()->showArticlesInView(m_masterDatabase, ui->clipsTreeView, m_filterMode);
m_publication.currentIssue()->section(sectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
if(m_runningMode != NORMAL_MODE && ui->preclipButton->text() == tr("Preclip") )
{
ui->fullpageView->removeImageCutouts();
m_tagsWrapper.clearTags();
m_tagsWrapper.showModel();
if(m_runningMode == CLIPPING_MODE)
drawerResetPages();
}
if ( ui->fullpageView->preselectedImageCutoutsCount() > 0 )
{
ui->fullpageView->removePreselectedImageCutouts();
m_tagsWrapper.clearTags();
m_tagsWrapper.showModel();
}
if(showArticleSelections)
{
ui->fullpageView->setPreselectedImageCutouts( m_publication.currentIssue()->getImageCutouts(articleId) );
m_tagsWrapper.setOcrTags(m_publication.currentIssue()->articleTags(articleId));
m_tagsWrapper.showModel();
}
m_imageModelIndex = index;
m_imageIndex = index.row();
m_clippedImageModelIndex = m_preclippedImageModelIndex = QModelIndex();
loadImage();
enableDrawerButtons(true);
setModifyClipButton(false);
m_runningMode = NORMAL_MODE;
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
}
}
void ClippingStation::articleTreeViewClicked(QModelIndex index)
{
qDebug("articleTreeViewClicked()");
static int clipid, preclipid;
if( !index.isValid() )
return;
QAbstractItemModel *model = ui->clipsTreeView->model();
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
//if the user clicked on top level entries, just return
if ( index == preclipRootIndex ||
index == clipRootIndex )
{
ui->clipsTreeView->expand(index);
return;
}
int id;
if ( index.parent() == preclipRootIndex ||
index.parent().parent() == preclipRootIndex )
{
QModelIndex currentIndex;
m_clippedImageModelIndex = QModelIndex();
//if the selection is the Preclip(), then it will contain the id
if(index.parent() == preclipRootIndex)
{
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
currentIndex = model->index(0, 0, index);
}
else
{
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
currentIndex = index;
}
if (currentIndex == m_preclippedImageModelIndex )
return; //if its the same selection, do nothing
if ( preclipid != id || m_currentPreclipId == 0 )
{
if(m_runningMode == CLIPPING_MODE)
drawerResetPages();
clipid = 0;
m_currentClipId = 0;
preclipid = id;
m_currentPreclipId = id;
m_firstPageInClip = "";
}
if (ui->preclipButton->text() != tr("Preclip"))
{
QList<Tag> tags = m_tagsWrapper.ocrTags();
m_tagsWrapper.setOcrTags( tags );
QList<ImageCutout*> cutoutsList = ui->fullpageView->imageCutoutsList();
m_publication.currentIssue()->preclip(id).setImageCutouts(cutoutsList);
}
else
m_tagsWrapper.setOcrTags( m_publication.currentIssue()->preclip(id).tags() );
ui->fullpageView->hideImageCutouts();
ui->fullpageView->removePreselectedImageCutouts();
ui->fullpageView->setImageCutouts(m_publication.currentIssue()->preclip(id).imageCutoutsList());
m_tagsWrapper.showModel();
//m_cachedImages.clear();
m_publication.currentIssue()->preclip(id).getImagesLocalAndRemoateFiles(m_preclippedLocalImagesList, m_preclippedRemoteImagesList);
m_preclippedImageIndex = currentIndex.row();
m_preclippedImageModelIndex = currentIndex;
QString section = model->data(currentIndex, Qt::DisplayRole).toString();
section = section.left(section.indexOf("/"));
m_currentSectionName = section;
QString fname = m_preclippedRemoteImagesList[0]; //its int the format of /ClippingStation/cach/2009/10/17/162/16/0001.jpg
QStringList list = fname.split("/");
m_currentIssueDate = list[list.count()-6] + "-" + list[list.count()-5]+ "-" + list[list.count()-4];
m_publication.setCurrentIssue(m_currentIssueDate);
m_publication.currentIssue()->section(m_currentSectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
ui->clipsTreeView->selectionModel()->clearSelection();
ui->clipsTreeView->selectionModel()->setCurrentIndex(m_preclippedImageModelIndex, QItemSelectionModel::Select);
//ui->clipsTreeView->expand(m_preclippedImageModelIndex.parent().parent() );
//ui->clipsTreeView->expand(m_preclippedImageModelIndex.parent() );
ui->clipsTreeView->expand(m_preclippedImageModelIndex );
enableDrawerButtons(true);
setModifyClipButton(false);
m_runningMode = PRECLIPPING_MODE;
}
else if ( index.parent() == clipRootIndex ||
index.parent().parent() == clipRootIndex )
{
m_runningMode = CLIPPING_MODE;
QModelIndex currentIndex;
m_preclippedImageModelIndex = QModelIndex();
//qDebug("Columns count is %d", model->columnCount(index.parent()) );
if(index.parent() == clipRootIndex)
{
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
currentIndex = model->index(0, 0, index);
}
else
{
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
currentIndex = index;
}
if (currentIndex == m_clippedImageModelIndex )
return; //if its the same selection, do nothing
if(clipid != id || m_currentClipId == 0)
{
drawerResetPages();
clipid = id;
m_currentClipId = id;
preclipid = 0;
m_currentPreclipId = 0;
m_firstPageInClip = "";
}
ui->fullpageView->hideImageCutouts();
ui->fullpageView->removePreselectedImageCutouts();
ui->fullpageView->setImageCutouts(m_publication.currentIssue()->clip(id).imageCutoutsList());
//m_cachedImages.clear();
m_publication.currentIssue()->clip(id).getImagesLocalAndRemoateFiles(m_clippedLocalImagesList, m_clippedRemoteImagesList);
m_tagsWrapper.setOcrTags( m_publication.currentIssue()->clip(id).tags() );
m_tagsWrapper.showModel();
m_clippedImageIndex = currentIndex.row();
m_clippedImageModelIndex = currentIndex;
//ui->clipsTreeView->expand(m_clippedImageModelIndex.parent().parent() );
//ui->clipsTreeView->expand(m_clippedImageModelIndex.parent() );
ui->clipsTreeView->expand(m_clippedImageModelIndex );
ui->clipsTreeView->selectionModel()->clearSelection();
ui->clipsTreeView->selectionModel()->setCurrentIndex(m_clippedImageModelIndex, QItemSelectionModel::Select);
QString section = model->data(currentIndex, Qt::DisplayRole).toString();
section = section.left(section.indexOf("/"));
m_currentSectionName = section;
QString fname = m_clippedRemoteImagesList[0]; //its int the format of G:/socialhose/app/ClippingStation/debug/cach/2009/10/17/162/16/0001.jpg
QStringList list = fname.split("/");
m_currentIssueDate = list[list.count()-6] + "-" + list[list.count()-5]+ "-" + list[list.count()-4];
m_publication.setCurrentIssue(m_currentIssueDate);
m_publication.currentIssue()->section(m_currentSectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
loadClippingImages(id);
}
loadImage();
gotoClipPage();
}
void ClippingStation::clearStatusMessage()
{
ui->statusBar->clearMessage();
}
void ClippingStation::displayStatusMessage(const QString & status)
{
ui->statusBar->showMessage(status);
}
void ClippingStation::displayCoordinatesStatus(qreal x, qreal y, qreal width, qreal height)
{
ui->statusBar->displayCoordinates(x, y, width, height);
}
void ClippingStation::displayRotationAngleStatus(qreal angle)
{
ui->statusBar->displayRotationAngle(angle);
}
void ClippingStation::updateDrawerPageInformation()
{
ui->pageInformation->setText(QString("Page %1 of %2")
.arg(ui->stackedDrawerViewWidget->currentIndex() +1)
.arg(ui->stackedDrawerViewWidget->count()));
}
void ClippingStation::displayZoomStatus(qreal zoom)
{
ui->statusBar->displayZoom(zoom);
}
void ClippingStation::firstPage()
{
if ( m_imageModelIndex.isValid() )
{
int oldindex = m_imageIndex;
m_imageIndex = 0;
if (!loadImage())
{
m_imageIndex = oldindex;
return;
}
m_imageModelIndex = ui->issuesTreeView->model()->index(0, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
ui->issuesTreeView->selectionModel()->clearSelection();
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
}
}
void ClippingStation::previousPage()
{
if ( m_imageIndex > 0 && m_imageModelIndex.isValid() )
{
--m_imageIndex;
if (!loadImage())
{
++m_imageIndex;
return;
}
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageModelIndex.row()-1, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
ui->issuesTreeView->selectionModel()->clearSelection();
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
}
}
void ClippingStation::nextPage()
{
if( m_imageIndex < m_localImagesList.count()-1 )
{
m_imageIndex++;
if (!loadImage())
{
--m_imageIndex;
return;
}
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageModelIndex.row()+1, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
ui->issuesTreeView->selectionModel()->clearSelection();
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
}
}
void ClippingStation::lastPage()
{
if ( m_imageModelIndex.isValid() )
{
int oldindex = m_imageIndex;
m_imageIndex = m_localImagesList.count() -1;
if (!loadImage())
{
m_imageIndex = oldindex;
return;
}
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageIndex, 0,ui->issuesTreeView->model()->parent(m_imageModelIndex) );
ui->issuesTreeView->selectionModel()->clearSelection();
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
}
}
void ClippingStation::gotoPage()
{
bool ok;
int pagenum = ui->gotoPageLineEdit->text().toInt(&ok);
if(!ok)
return;
if( m_imageModelIndex.isValid() )
{
if ( pagenum < 1 || pagenum > m_localImagesList.count() )
return;
int oldindex = m_imageIndex;
m_imageIndex = pagenum -1 ;
if(!loadImage())
{
m_imageIndex = oldindex;
return;
}
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageIndex, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
ui->issuesTreeView->selectionModel()->clearSelection();
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
}
}
void ClippingStation::gotoClipPage()
{
//qDebug("gotoClipPage()");
QAbstractItemModel* model = ui->issuesTreeView->model();
int issuesCount = model->rowCount( QModelIndex() );
QString article;
if(m_runningMode == PRECLIPPING_MODE)
article = ui->clipsTreeView->model()->data(m_preclippedImageModelIndex, Qt::DisplayRole).toString();
else if(m_runningMode == CLIPPING_MODE)
article = ui->clipsTreeView->model()->data(m_clippedImageModelIndex , Qt::DisplayRole).toString();
for(int i=0; i< issuesCount; i++)
{
QString issue = model->index(i, 0, QModelIndex() ).data(Qt::DisplayRole).toString();
if(issue != m_currentIssueDate)
continue;
QModelIndex issueIndex = model->index(i, 0, QModelIndex() );
int sectionsCount = model->rowCount(issueIndex);
for(int j=0; j < sectionsCount; j++)
{
QString section = model->index(j, 0, issueIndex).data(Qt::DisplayRole).toString();
if( article.split("/").at(0) != section )// != m_currentSectionName)
continue;
QModelIndex sectionIndex = model->index(j, 0, issueIndex);
int pagesCount = model->rowCount(sectionIndex);
for(int k=0; k< pagesCount; k++)
{
QString page = model->index(k, 0, sectionIndex).data(Qt::DisplayRole).toString();
if( !article.endsWith(page) )
continue;
m_imageModelIndex = model->index(k, 0, sectionIndex);
ui->issuesTreeView->selectionModel()->clearSelection();
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
ui->issuesTreeView->expand(m_imageModelIndex.parent().parent());
ui->issuesTreeView->expand(m_imageModelIndex.parent());
//ui->issuesTreeView->expand(m_imageModelIndex);
}
return;
}
return;
}
}
void ClippingStation::rotate(double i)
{
ui->fullpageView->rotate(i);
if(i == 0)
ui->saveRotateButton->setEnabled(false);
else
ui->saveRotateButton->setEnabled(true);
}
void ClippingStation::saveImageRotation()
{
//we first get the ORIGINAL image from the file server
//we get its name/path
QString localeImage, remoteImage;
if(m_runningMode == NORMAL_MODE)
{
localeImage = m_localImagesList[m_imageIndex];
remoteImage = m_remoteImagesList[m_imageIndex];
}
else if (m_runningMode == PRECLIPPING_MODE)
{
localeImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
remoteImage = m_preclippedRemoteImagesList[m_preclippedImageIndex];
}
else if (m_runningMode == CLIPPING_MODE )
{
localeImage = m_clippedLocalImagesList[m_clippedImageIndex];
remoteImage = m_clippedRemoteImagesList[m_clippedImageIndex];
}
QImage image(remoteImage);
//do the roation
double rotate = ui->rotateSpinBox->value();
QTransform mx;
mx = mx.rotate(rotate);
image = image.transformed(mx, Qt::SmoothTransformation);
//now we delete the original image, and save this back to that location
if (QFile::remove(remoteImage) )
{
image.save(remoteImage, "jpg", JPG_SAVE_QUALITY);
//also remove the file from the local cache
QFile::remove(localeImage);
//reset the rotate spin box
ui->rotateSpinBox->setValue(0);
//and re open the new image after it has been saved
m_cachedImages[ localeImage ] = false; //to force to reload the new image from server
loadImage();
}
//also, load the 300dpi image, and rotate it as well
QFileInfo inf(remoteImage);
QString img300dpi= inf.absolutePath() + "/" + HIGH_RES_IMAGE_DIR + inf.fileName();
if(!QFile::exists(img300dpi))
return;
QImage image300(img300dpi);
image300 = image300.transformed(mx, Qt::SmoothTransformation);
//now we delete the original image, and save this back to that location
if (QFile::remove(img300dpi) )
image300.save(img300dpi, "jpg", JPG_SAVE_QUALITY);
}
qreal ClippingStation::zoomOut()
{
ui->bestFitButton->setChecked(false);
ui->widthFitButton->setChecked(false);
ui->fullpageView->setPageLayout(ACTUAL_SIZE);
return ui->fullpageView->zoom(false);
}
qreal ClippingStation::zoomIn()
{
ui->bestFitButton->setChecked(false);
ui->widthFitButton->setChecked(false);
ui->fullpageView->setPageLayout(ACTUAL_SIZE);
return ui->fullpageView->zoom(true);
}
qreal ClippingStation::actualSize()
{
ui->bestFitButton->setChecked(false);
ui->widthFitButton->setChecked(false);
ui->fullpageView->setPageLayout(ACTUAL_SIZE);
return ui->fullpageView->actualSize();
}
void ClippingStation::bestFit()
{
ui->bestFitButton->setChecked(true);
ui->widthFitButton->setChecked(false);
ui->fullpageView->setPageLayout(BEST_FIT);
}
void ClippingStation::widthFit()
{
ui->bestFitButton->setChecked(false);
ui->widthFitButton->setChecked(true);
ui->fullpageView->setPageLayout(WIDTH_FIT);
}
qreal ClippingStation::drawerZoomOut()
{
ui->drawerBestFitButton->setChecked(false);
ui->drawerWidthFitButton->setChecked(false);
int index = ui->stackedDrawerViewWidget->currentIndex();
//ui->stackedDrawerViewWidget->setCurrentIndex(0);
qreal scale = 1.0;
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
ui->stackedDrawerViewWidget->setCurrentIndex(i);
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
scale = view->zoom(false);
m_currentA4Scale = view->currentScale();
}
ui->stackedDrawerViewWidget->setCurrentIndex(index);
return scale;
}
qreal ClippingStation::drawerZoomIn()
{
ui->drawerBestFitButton->setChecked(false);
ui->drawerWidthFitButton->setChecked(false);
int index = ui->stackedDrawerViewWidget->currentIndex();
//ui->stackedDrawerViewWidget->setCurrentIndex(0);
qreal scale = 1.0;
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
ui->stackedDrawerViewWidget->setCurrentIndex(i);
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
scale = view->zoom(true);
m_currentA4Scale = view->currentScale();
}
ui->stackedDrawerViewWidget->setCurrentIndex(index);
return scale;
}
qreal ClippingStation::drawerActualSize()
{
ui->drawerBestFitButton->setChecked(false);
ui->drawerWidthFitButton->setChecked(false);
int index = ui->stackedDrawerViewWidget->currentIndex();
ui->stackedDrawerViewWidget->setCurrentIndex(0);
qreal scale = 1.0;
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
view->setPageLayout(ACTUAL_SIZE);
scale = view->actualSize();
m_currentA4Scale = view->currentScale();
}
ui->stackedDrawerViewWidget->setCurrentIndex(index);
return scale;
}
void ClippingStation::drawerBestFit()
{
ui->drawerBestFitButton->setChecked(true);
ui->drawerWidthFitButton->setChecked(false);
int index = ui->stackedDrawerViewWidget->currentIndex();
ui->stackedDrawerViewWidget->setCurrentIndex(0);
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
view->setPageLayout(BEST_FIT);
m_currentA4Scale = view->currentScale();
}
ui->stackedDrawerViewWidget->setCurrentIndex(index);
}
void ClippingStation::drawerWidthFit()
{
ui->drawerBestFitButton ->setChecked(false);
ui->drawerWidthFitButton->setChecked(true);
int index = ui->stackedDrawerViewWidget->currentIndex();
ui->stackedDrawerViewWidget->setCurrentIndex(0);
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
view->setPageLayout(WIDTH_FIT);
m_currentA4Scale = view->currentScale();
}
ui->stackedDrawerViewWidget->setCurrentIndex(index);
}
bool ClippingStation::loadImage()
{
// qDebug("loadImage()");
// clock_t start = clock();
static bool firstPage = true;
m_trackingTimer.stop();
/*
------------------------
| id_user_page_track |
| id_users |
| id_section_pages |
| last_modified |
| first_access |
| last_access |
| issue_created |
| id_publication |
| id_publication_type |
| publication_language |
| publication_market |
| issue_date |
| seconds |
------------------------
*/
if(!firstPage && m_trackingSeconds > 0)
{
QString language = "en";
if(m_publication.language() == "Arabic")
language = "ar";
m_user.updateTrack(m_currentPageId, m_trackingSeconds);
}
bool ret = true;
QString localeImage, remoteImage;
if (m_runningMode == NORMAL_MODE)
{
qDebug() << "\tImage: "<< m_remoteImagesList[m_imageIndex];
localeImage = m_localImagesList[m_imageIndex];
remoteImage = m_remoteImagesList[m_imageIndex];
}
else if (m_runningMode == PRECLIPPING_MODE)
{
qDebug() << "\tPreclipping Image: "<< m_preclippedRemoteImagesList[m_preclippedImageIndex];
localeImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
remoteImage = m_preclippedRemoteImagesList[m_preclippedImageIndex];
}
else if (m_runningMode == CLIPPING_MODE )
{
qDebug() << "\tClipping Image: "<< m_clippedRemoteImagesList[m_clippedImageIndex];
localeImage = m_clippedLocalImagesList[m_clippedImageIndex];
remoteImage = m_clippedRemoteImagesList[m_clippedImageIndex];
}
/*int lockedBy;
if( isImageLocked(localeImage, lockedBy) )
{
QString username = User::username(m_slaveDatabase, lockedBy);
QMessageBox::warning(this, tr("Page Locked"), tr("You cant load this page because its locked by user (%1)").arg(username) );
return false;
}
lockImage(localeImage);*/
if( !m_cachedImages[ localeImage ] )
{
if ( !m_imageCachingDialog.cachingThreadStarted() )
{
ret = cacheOnePage(remoteImage, localeImage);
}
else
{
m_imageCachingDialog.pause();
ret = cacheOnePage(remoteImage, localeImage);
}
}
if(ret)
ret = ui->fullpageView->load(localeImage);
if(ret)
{
QStringList parts = localeImage.split("/");
QString image = parts[parts.count()-1];
m_currentPageId = getImageId(image);
loadImageHighlights(m_currentPageId);//load the highlights
}
// double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
// qDebug("loadImage() Time: %f", diff);
cache();
if(m_isPaused) //if in pause state, change it to resume.
pauseTracking();
m_trackingSeconds = 0;
m_trackingTimer.start(1000);
int pubIssueId = publicationIssueId(m_publication.id(), m_publication.currentIssue()->date());
int issueSecId = issueSectionsId(pubIssueId, m_publication.currentIssue()->section(m_currentSectionName).id());
m_user.track(m_currentPageId, m_publication.id(), pubIssueId, issueSecId,
m_publication.type(), m_publication.country().toInt(),
m_publication.language(), m_publication.currentIssue()->date(), m_publication.currentIssue()->created());
firstPage = false;
return ret;
}
void ClippingStation::cache()
{
//qDebug("cache()");
clock_t start = clock();
if(m_runningMode == NORMAL_MODE)
m_imageCachingDialog.setValues(m_remoteImagesList, m_localImagesList);
else if(m_runningMode == CLIPPING_MODE )
m_imageCachingDialog.setValues(m_clippedRemoteImagesList, m_clippedLocalImagesList);
else if(m_runningMode == PRECLIPPING_MODE )
m_imageCachingDialog.setValues(m_preclippedRemoteImagesList, m_preclippedLocalImagesList);
m_imageCachingDialog.startCaching();
m_imageCachingDialog.show(); //m_imageCachingDialog.exec();
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("cache() Time: %f", diff);
}
bool ClippingStation::cacheOnePage(QString srcPage, QString dstPage)
{
clock_t start = clock();
m_imageCachingDialog.pause();
return m_imageCachingDialog.cacheOnePage(srcPage, dstPage);
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("cacheOnePage() Time: %f", diff);
}
bool ClippingStation::recursiveDelete(const QDir &dir)
{
QList<QFileInfo> infLst = dir.entryInfoList();
foreach(QFileInfo finfo, infLst )
{
if(finfo.fileName() == "." || finfo.fileName() == ".." )
continue;
if(finfo.isDir() )
{
QDir subDir(finfo.absoluteFilePath());
qDebug() << "SubDir: " << subDir.absolutePath().toLocal8Bit();
QDir dir1 = dir;
if ( recursiveDelete(subDir) )
{
dir1.cdUp();
if ( !dir1.rmdir(finfo.absoluteFilePath() ) )
{
qDebug() << "Error deleting directory: " << finfo.absoluteFilePath().toLocal8Bit();
}
}
}
else
{ //file
QDir dir1;
if( !dir1.remove(finfo.absoluteFilePath()) )
qDebug() << "Error deleting file: " << finfo.absoluteFilePath();
}
}
return true;
}
void ClippingStation::searchKeyword()
{
QString search = ui->keywordLineEdit->text();
if( search.isEmpty() || search.isNull() )
return;
m_tagsWrapper.searchKeyword(m_masterDatabase, search);
}
void ClippingStation::checkAllKeywords()
{
m_tagsWrapper.checkAllKeywords();
}
void ClippingStation::uncheckAllKeywords()
{
m_tagsWrapper.uncheckAllKeywords();
}
void ClippingStation::selectKeyword()
{
m_tagsWrapper.selectKeyword();
}
void ClippingStation::clipsTreeContextMenu(QPoint point)
{
QModelIndex index = ui->clipsTreeView->indexAt(point);
if( index.isValid() )
{
point.setY(point.y() + 25);
QAbstractItemModel *model = ui->clipsTreeView->model();
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
//if the user clicked on top level entries, just return
if ( index == preclipRootIndex ||
index == clipRootIndex )
return;
int id;
if ( index.parent() == preclipRootIndex ||
index.parent().parent() == preclipRootIndex )
{
m_runningMode = PRECLIPPING_MODE;
QModelIndex currentIndex;
m_clippedImageModelIndex = QModelIndex();
//if the selection is the Preclip(), then it will contain the id
if(index.parent() == preclipRootIndex)
{
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
//currentIndex = index.child(0, 0);
}
else
{
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
//currentIndex = index;
}
m_preclipContextMenu->exec( ui->clipsTreeView->mapToGlobal(point));
}
else
{
m_clipContextMenu->exec( ui->clipsTreeView->mapToGlobal(point));
}
}
}
void ClippingStation::issueTreeContextMenu(QPoint point)
{
QModelIndex index = ui->issuesTreeView->indexAt(point);
if( index.isValid() )
{
point.setY(point.y() + 25);
QAbstractItemModel *model = ui->issuesTreeView->model();
if(index == QModelIndex() )
return;
if(model->parent(index) == QModelIndex() )
{
m_issueContextMenu->exec(ui->issuesTreeView->mapToGlobal(point));
return;
}
if(model->parent(index).parent() == QModelIndex() )
return;
if(model->parent(index).parent().parent() == QModelIndex() ) //its the image
m_issuePageContextMenu->exec( ui->issuesTreeView->mapToGlobal(point));
else
qDebug() << "not an image selection";
}
}
void ClippingStation::keywordsTreeContextMenu(QPoint point)
{
QModelIndex index = ui->treeView->indexAt(point);
if(!index.isValid())
return;
point.setY(point.y()+25);
// QAbstractItemModel *model = ui->treeView->model();
m_keywordsContextMenu->exec( ui->treeView->mapToGlobal(point));
}
void ClippingStation::preclip()
{
qDebug("preclip()");
QList<ImageCutout *> cutoutsList = ui->fullpageView->imageCutoutsList();
if(cutoutsList.count() == 0)
{
QMessageBox::information(this, "No selections", "Please select at least one cutout to be able to clip");
return;
}
QList<Tag> tags = m_tagsWrapper.ocrTags();
if( tags.count() == 0 )
{
QMessageBox::information(this, "No Tags", "Please add the associated tags to be able to clip");
return;
}
qreal image_size = ui->fullpageView->pageSize();
if(ui->preclipButton->text() == tr("Modify"))
{
m_publication.currentIssue()->preclip(m_currentPreclipId).updateArticle(m_masterDatabase, m_publication, tags, cutoutsList, image_size);
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, m_currentPreclipId, false, true);
}
else
{
int articleId = Article::clip(m_masterDatabase, m_publication, m_user.id(), tags, cutoutsList, m_currentSectionName, image_size, 0, 1, "");
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, articleId, false, false);
}
drawerResetPages();
m_firstPageInClip = ""; //reset pages for clipping
m_currentPreclipId = 0; //reset the preclip id;
m_currentClipId = 0;
//loadIssuesWithPreclipsOnly();
m_tagsWrapper.clearTags();
ui->fullpageView->removeImageCutouts();
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
setModifyPreclipButton(false);
m_runningMode = NORMAL_MODE;
ui->statusBar->showMessage("Preclipping successfull");
qDebug("end of preclip()");
}
void ClippingStation::clip()
{
qDebug("clip()");
qDebug("before cutoutList()");
QList<ImageCutout *> cutoutsList = ui->fullpageView->imageCutoutsList();
if(cutoutsList.count() == 0)
{
QMessageBox::information(this, "No selections", "Please select at least one area to be able to clip");
return;
}
qDebug("before ocrTags()");
QList<Tag> tags = m_tagsWrapper.ocrTags();
if( tags.count() == 0 )
{
QMessageBox::information(this, "No Tags", "Please add the associated tags to be able to clip");
return;
}
static QSqlDatabase db = m_masterDatabase.cloneDatabase(m_masterDatabase, "master2222");
db.open();
if (m_runningMode != CLIPPING_MODE)
{
int cutoutsCount = totalNumberOfCutoutsInDrawer();
if( cutoutsCount <= 0 )
{
QMessageBox::information(this, "Blank clipping", "Please add the cut outs be able to clip");
return;
}
QStringList pages = emptyDrawerPages();
if(pages.count() > 0)
{
QString page;
if(pages.count() == 1)
page = QString("Page (%1) in drawer is empty, please remove it before clipping").arg(pages[0]);
else
page = QString("Pages (%1) in drawer are empty, please remove them before clipping").arg(pages.join(","));
QMessageBox::information(this, "Empty pages", page);
return;
}
if( cutoutsList.count() > cutoutsCount )
{
switch( QMessageBox::question(
this,
tr("Warning"),
tr("You only copied %1/%2 cutouts from left pane, Do you want to CONTINUE the clipping process?").arg( cutoutsCount ).arg( cutoutsList.count() ),
QMessageBox::Yes |
QMessageBox::No,
QMessageBox::No) )
{
case QMessageBox::Yes:
break;
case QMessageBox::No:
return;
default:
return;
}
}
}
if (m_runningMode == PRECLIPPING_MODE)
{
int images_number = ui->stackedDrawerViewWidget->count(); //the count of image
QString text = ui->fullpageView->text();
bool isArabic = (m_publication.language() == "Arabic");
m_publication.currentIssue()->preclip(m_currentPreclipId).updateTags(m_masterDatabase, tags, isArabic);
m_publication.currentIssue()->preclip(m_currentPreclipId).updateImagesNumber(m_masterDatabase, images_number);
m_publication.currentIssue()->preclip(m_currentPreclipId).updateProminence(m_masterDatabase, m_publication, tags, m_user.id());
QList<QImage> list = createClipImages();
bool ret = true;
if(m_useFtp)
{
QFuture<bool> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFtpServer(m_currentIssueDate, m_currentPreclipId, list, true, m_masterDatabase); });
m_saveClipImagesToFtpServerWatcher.setFuture(future);
}
else
{
QFuture<int> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFileServer(m_currentIssueDate, m_currentPreclipId, list); });
m_saveClipImagesToFileServerWatcher.setFuture(future); //ret = saveClipImagesToFileServer(m_currentPreclipId, list); //save the clip images in the clip directories
//ret = saveClipImagesToFileServer(m_currentIssueDate, m_currentPreclipId, list, true, m_masterDatabase);
}
if(!m_publication.skipOcr())
{
qDebug() << m_publication.name() << " not skip OCR, Insert to db";
bool isArabic = (m_publication.language() == "Arabic");
QFuture<bool> future2 = QtConcurrent::run([=]() mutable { return addTextToClip(m_currentPreclipId, cutoutsList, db, isArabic); });
m_addTextToClipWatcher.setFuture(future2);
}
else
qDebug() << m_publication.name() << " has skip OCR set, wont insert text to db";
if(!ret)
{
m_publication.currentIssue()->preclip(m_currentPreclipId).updateStatus(m_masterDatabase, 1);
ui->statusBar->showMessage("Clipping Error");
}
else
{
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, m_currentPreclipId, true, true);
ui->statusBar->showMessage("Clipping successfull");
}
}
else if (m_runningMode == CLIPPING_MODE)
{
bool isArabic = (m_publication.language() == "Arabic");
m_publication.currentIssue()->clip(m_currentClipId).updateTags(m_masterDatabase, tags, isArabic);
m_publication.currentIssue()->clip(m_currentClipId).updateProminence(m_masterDatabase, m_publication, tags, m_user.id());
ui->statusBar->showMessage("Clip modified successfully");
}
else //fresh clip
{
qreal image_size = ui->fullpageView->pageSize();
int images_number = ui->stackedDrawerViewWidget->count(); //the cound of image
QString text = ui->fullpageView->text();
int id_article = Article::clip(m_masterDatabase, m_publication, m_user.id(), tags, cutoutsList, m_currentSectionName, image_size, images_number, 1);
//create the images
QList<QImage> list = createClipImages();
bool ret = true;
if(m_useFtp)
{
QFuture<bool> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFtpServer(m_currentIssueDate, id_article, list, false, m_masterDatabase); });
m_saveClipImagesToFtpServerWatcher.setFuture(future);
}
else
{
QFuture<int> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFileServer(m_currentIssueDate, id_article, list); });
m_saveClipImagesToFileServerWatcher.setFuture(future); //ret = saveClipImagesToFileServer(m_currentPreclipId, list); //save the clip images in the clip directories
//ret = saveClipImagesToFileServer(m_currentIssueDate, id_article, list, true, m_masterDatabase);
}
if(!m_publication.skipOcr())
{
qDebug() << m_publication.name() << " No skip OCR set, insert text to db";
//QSqlDatabase db = m_masterDatabase.cloneDatabase(m_masterDatabase, "master2222");
//db.open();
bool isArabic = (m_publication.language() == "Arabic");
QFuture<bool> future2 = QtConcurrent::run([=]() mutable { return addTextToClip(id_article, cutoutsList, db, isArabic); });
m_addTextToClipWatcher.setFuture(future2);
}
else
qDebug() << m_publication.name() << " has skip OCR set, wont insert text to db";
if(!ret)
{
Article::deleteArticle(m_masterDatabase, id_article);
ui->statusBar->showMessage("Clipping Error");
}
else
{
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, id_article, true, false);
ui->statusBar->showMessage("Clipping successfull");
}
}
drawerResetPages();
m_firstPageInClip = ""; //reset pages for clipping
m_currentPreclipId = 0; //reset the preclip id;
m_currentClipId = 0;
//if (m_filterMode == PRECLIPSONLY_FILTER)
//loadIssuesWithPreclipsOnly();
ui->fullpageView->removeImageCutouts();
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
m_tagsWrapper.clearTags();
//m_tagsWrapper.showModel();
m_runningMode = NORMAL_MODE;
if (m_filterMode == PRECLIPSONLY_FILTER)
{
//go to the next preclip
QAbstractItemModel *model = ui->clipsTreeView->model();
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
//if(preclipRootIndex.model()->children().count() > 0)
{
QModelIndex pindex = model->index(0, 0, preclipRootIndex);
if(pindex.isValid())
articleTreeViewClicked(pindex);
else
{
//we have reached the end of this issues preclip, so, remove the issue from list.
m_publication.removeIssueFromIssues(ui->issuesTreeView, m_currentIssueDate);
m_currentIssueDate = "";
//now go to the next issue
QAbstractItemModel *model = ui->issuesTreeView->model();
QModelIndex issuesIndex = model->index(0, 0, QModelIndex() );
if( issuesIndex.isValid() )
issueTreeViewItemClicked(issuesIndex);
else
{
//remove the publication from the drop-down list
ui->preclippedPublicationComboBox->removeItem(ui->preclippedPublicationComboBox->currentIndex());
}
}
}
}
qDebug("end of clip()");
}
void ClippingStation::drawerResetPages()
{
qDebug("drawerResetPages()");
int count = ui->stackedDrawerViewWidget->count();
for(int i=count -1 ; i >= 0; i--)
{
ui->stackedDrawerViewWidget->setCurrentIndex(i);
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
ui->stackedDrawerViewWidget->removeWidget( ui->stackedDrawerViewWidget->widget(i) );
delete view;
}
drawerAddPage(true);
}
void ClippingStation::drawerAddPage(bool isfirst)
{
DrawerView * newview = new DrawerView(isfirst, ui->page);
qreal oldscale = 1.0; //for the first page insertion
//first we restore all the current pages to actual size, add the new page, and then restore them back to current size;
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
oldscale = view->actualSize();
}
ui->stackedDrawerViewWidget->addWidget(newview);
//restore to old scale value
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
view->setScale(oldscale);
}
ui->stackedDrawerViewWidget->setCurrentIndex(ui->stackedDrawerViewWidget->count() - 1);
if(isfirst)
drawerBestFit(); //best fit mod
// else
// newview->setPageLayout(ACTUAL_SIZE);
m_currentA4Scale = newview->currentScale();
//qDebug("Add Page scale %.2f", m_currentA4Scale);
updateDrawerPageInformation();
connect(newview, SIGNAL(createThumbnail()), this, SLOT(createThumbnail()));
}
void ClippingStation::drawerRemovePage()
{
int i = ui->stackedDrawerViewWidget->currentIndex();
if (i == 0) //first page
{
QMessageBox::critical(this, "Error", "You cant remove the first page in drawer");
return;
}
switch( QMessageBox::question(
this,
tr("Delete Page"),
tr("Delete page from the Drawer, are you sure?"),
QMessageBox::Yes |
QMessageBox::No,
QMessageBox::No) )
{
case QMessageBox::Yes:
break;
case QMessageBox::No:
return;
default:
return;
}
//DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
//view->removeEventFilter(this);
ui->stackedDrawerViewWidget->removeWidget( ui->stackedDrawerViewWidget->widget(i) );
updateDrawerPageInformation();
}
void ClippingStation::drawerPreviousPage()
{
int currentIndex = ui->stackedDrawerViewWidget->currentIndex();
if (currentIndex != 0)
{
A4Scale();
ui->stackedDrawerViewWidget->setCurrentIndex(currentIndex-1);
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget());
view->setScale(m_currentA4Scale);
updateDrawerPageInformation();
}
}
void ClippingStation::drawerNextPage()
{
int currentIndex = ui->stackedDrawerViewWidget->currentIndex();
if (currentIndex != ui->stackedDrawerViewWidget->count() - 1)
{
A4Scale();
ui->stackedDrawerViewWidget->setCurrentIndex(currentIndex+1);
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget());
view->setScale(m_currentA4Scale);
updateDrawerPageInformation();
}
}
QList<QImage> ClippingStation::createClipImages()
{
QList<QImage> list;
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
ui->stackedDrawerViewWidget->setCurrentIndex(i);
if(view->cutoutsCount() > 0)
{
QImage img = view->screenShot();
list.append(img);
}
}
return list;
}
int ClippingStation::saveClipImagesToFileServer(QString currentIssue, int id_article, QList<QImage> &list)
{
g_clipMutex.lock();
qDebug("saveClipImages() for article %d", id_article);
//we save the images on this format ClippingsPath/YYYY/MM/DD/ID_ARTICLE-X
QString path = SystemConfiguration::clippingsPath();
QStringList dateSplit = currentIssue.split("-");
path = path + QString("%1/%2/%3/").arg(dateSplit[0], 4, QChar('0')).arg(dateSplit[1], 2, QChar('0')).arg(dateSplit[2], 2, QChar('0'));
#ifdef Q_WS_WIN
path = SystemConfiguration::clippingsWindowsDriveLetter() + path; //if we are under Windows, add Windows drive letter
#endif
QDir dir;
qDebug("saveClipImages() for article %d: create the directory structure", id_article);
if( !dir.exists(path) )
{
if( !dir.mkpath(path) )
{
QMessageBox::critical(0, tr("saveClipImagesToFileServer() Error"), tr("Error creating directory structure for clippings!"));
qDebug("saveClipImagesToFileServer(): Error creating directory ");
g_clipMutex.unlock();
return 0;
}
}
bool ret = true;
int i = 0;
//first save the file locally, and then move it the file server
qDebug("saveClipImages(): create clippings directory in cache");
QString localpath = m_cacheDir + "clippings/";
QDir dir2;
if( !dir2.exists(localpath) )
{
if( !dir2.mkpath(localpath) )
{
QMessageBox::critical(0, tr("saveClipImagesToFileServer() Error"), tr("Error creating directory structure for local clippings!"));
qDebug("saveClipImagesToFileServer(): Error creating directory ");
g_clipMutex.unlock();
return 0;
}
}
qDebug("saveClipImages(): trying to save %d images", list.count() );
QFile file;
for(i=0; i< list.count(); i++)
{
QString fname = QString("%1-%2.jpg").arg(id_article).arg(i+1);
//if( file.exists(localpath + fname) || file.exists(path + fname) ) //try to remove the files if they exist
{
file.remove(localpath+ fname); //remove the file from cache if it already exist (from previous un-successful clip)
file.remove(path + fname); //and from the file server
}
ret = list[i].save(localpath + fname, "jpg", 100);
if(ret)
{
qDebug() << "saveClipImages(): saving image " << localpath+fname << " Successfull";
if (file.copy(localpath + fname, path + fname))
qDebug() << "saveClipImages(): copying image to " << path + fname << " Successfull";
else
{
qDebug() << "saveClipImages(): copying image to " << path + fname << " Unsuccessfull: reason: " << file.errorString();
ret = false;
break;
}
}
else
{
qDebug() << "saveClipImages(): Saving image " << fname << " Unsuccessfull";
ret = false;
break;
}
}
if(!ret)
{
//error happend in the complete set of images, so we delete what is already created
qDebug() << "saveClipImages(): Error happened while saving, remove the saved images!";
for(int j=0; j< i; j++)
{
QString fname = QString("%1-%2.jpg").arg(id_article).arg(j+1);
file.remove(localpath +fname); //remove it locally
file.remove(path +fname); //and from file server
}
g_clipMutex.unlock();
return 0;
}
//we also check to see if the image does REALLY exist on that folder
qDebug() << "saveClipImages(): Checking if the images exist on the server and the images sizes is larger than 30kb";
for(int i=0; i< list.count(); i++)
{
QString fname = path + QString("%1-%2.jpg").arg(id_article).arg(i+1);
QFileInfo fi(fname);
if( !fi.exists() || (fi.size() < 20 * 1024))
{
qDebug() << "saveClipImages(): Image " << fname << " DOES not exist, or size less than 30 kb: " << file.errorString();
ret= false;
break;
}
else
qDebug() << "saveClipImages(): Image " << fname << " exist on the server";
}
//now save the thumbnail to server
qDebug() << "saveClipImages(): save the thumbnail";
QString thumbnailName = QString("%1_thumb.jpg").arg(id_article);
if(file.exists(localpath+ thumbnailName))
{
file.remove(localpath + thumbnailName);
file.remove(path + thumbnailName);
}
m_thumbnail.save(localpath + thumbnailName, "jpg", 100);
file.copy(localpath + thumbnailName, path + thumbnailName);
qDebug() << "saveClipImages(): save the thumbnail DONE";
/*
qDebug() << "saveClipImages(): Trying to open the saved images";
for(int i=0; i< list.count(); i++)
{
QString fname = path + QString("%1-%2.jpg").arg(id_article).arg(i+1);
QFile file(fname);
if( !file.open(QFile::ReadOnly) )
{
qDebug() << "saveClipImages(): Image " << fname << " DOES not open, reason: " << file.errorString();
ret= false;
break;
}
else
qDebug() << "saveClipImages(): Image " << fname << " opens OK";
file.close();
}
*/
if(ret)
{
Article::updateImagesNumber(m_clipDatabase, id_article, list.count());
Article::updateStatus(m_clipDatabase, id_article, 2);
qDebug("saveClipImages(): Everything is OK for article %d, updating the status =2 and images number = %d", id_article, list.count());
g_clipMutex.unlock();
return id_article;
}
//if error happens, return to preclip, if pre-clip, or delete it from clipping
Article::updateImagesNumber(m_clipDatabase, id_article, 0);
qDebug("saveClipImages(): Error happend for article %d. roll back to original values", id_article);
g_clipMutex.unlock();
return 0;
}
bool ClippingStation::saveClipImagesToFtpServer (QString &currentIssue, int &id_article, QList<QImage> &list, bool fromPreclip, QSqlDatabase &database)
{
QString path = SystemConfiguration::clippingsPath();
QStringList dateSplit = currentIssue.split("-");
path = path + QString("%1/%2/%3/").arg(dateSplit[0], 4, QChar('0')).arg(dateSplit[1], 2, QChar('0')).arg(dateSplit[2], 2, QChar('0'));
CURL *curlhandle = NULL; //the libcurl easy handle
path = QString("ftp://%1:%2@%3/").arg(m_username).arg(m_password).arg(m_address) + path;
curl_global_init(CURL_GLOBAL_ALL); //initate it
curlhandle = curl_easy_init();
bool ret = true;
char str[255];
saveClipImagesToFtpServerErrorMsg = "";
for(int i=0; i< list.count(); i++)
{
QString tmpfilename = QString("%1-%2.jpg").arg(id_article).arg(i+1);
QString filename = path + tmpfilename;
if( list[i].save(tmpfilename, "jpg", 100) )
{
ret = upload(curlhandle, filename.toLocal8Bit(), tmpfilename.toLocal8Bit(), 0, 3, str);
if(!ret)
{
qDebug() << "saveClipImagesToFtpServer(): Error uploading image " << filename.toLocal8Bit() << ": " << str;
QFile::remove(tmpfilename);
saveClipImagesToFtpServerErrorMsg = str;
ret = false;
break;
}
QFile::remove(tmpfilename);
}
else
{
ret = false;
break;
}
}
//now save the thumbnail image as well
{
QString tmpfilename = QString("%1_thumb.jpg").arg(id_article);
QString filename = path + tmpfilename;
if( m_thumbnail.save(tmpfilename, "jpg", 100) )
{
ret = upload(curlhandle, filename.toLocal8Bit(), tmpfilename.toLocal8Bit(), 0, 3, str);
if(!ret)
{
qDebug() << "saveClipImagesToFtpServer(): Error uploading image " << filename.toLocal8Bit() << ": " << str;
QFile::remove(tmpfilename);
saveClipImagesToFtpServerErrorMsg = str;
//ret = false;
//break;
}
QFile::remove(tmpfilename);
}
}
if(ret)
return true;
if(fromPreclip)
Article::updateStatus(database, id_article, 1);
else
Article::deleteArticle(database, id_article);
return false;
}
bool ClippingStation::addTextToClip(int id_article, QList<ImageCutout*> &list, QSqlDatabase &database, bool isArabic)
{
//first, get the words from database, and then get the text and add it to database.
qDebug() << "addTextToClip()";
QStringList pages = ImageCutout::fullPages(list);
QHash<QString, QList<WordCoordinates> > wcHash;
for(int i=0; i< pages.count(); i++)
{
QList<WordCoordinates> wc = loadImageText(pages[i], database);
qDebug("word counts = %d", wc.count());
wcHash.insert(pages[i], wc);
}
QString headline = "";
//now get coordinates of the text
QString text = "";
for(int i=0; i< list.count(); i++)
{
QString pagename = list[i]->pageName();
QString t = getTextFromCutout( list[i]->boundingRect().toRect(), wcHash.value(pagename) );
text+= t + " ";
if(list[i]->areaType() == TITLE)
headline += t + " ";
}
qDebug() << "addTextToClip() headline is : " << headline;
qDebug() << "addTextToClip() Text is : " << text;
//now add the text to clip.
Article::updateText(database, id_article, text);
if(headline.trimmed().isEmpty())
{
int index = text.indexOf("\n");
if(index > -1 && index < text.length())
headline = text.left(index);
else
headline = text.left(100).trimmed();
qDebug() << "addTextToClip() new headline is : " << headline;
}
if(!headline.trimmed().isEmpty())
Article::updateHeadline(database, id_article, headline, isArabic);
qDebug() << "end of addTextToClip()";
return true;
}
QString ClippingStation::getTextFromCutout( QRect rect, QList<WordCoordinates> wc )
{
QStringList words;
for(int i=0; i<wc.count(); i++)
{
Coordinates crd = wc[i].coordinates();
QPointF pt1(crd.left(), crd.top());
QPointF pt2(crd.right(), crd.bottom());
QRectF rec(pt1, pt2);
if( rect.contains( rec.toRect() ) )
words.append(wc[i].word());
}
return words.join(" ");
}
void ClippingStation::saveClipImagesToFtpServerWatcherFinished()
{
bool t = m_saveClipImagesToFtpServerWatcher.result();
if(!t) //if error happen, show a message
QMessageBox::critical(this, tr("Ftp Clipping Error"), tr("Error uploading clipping images to Ftp (%1)").arg(saveClipImagesToFtpServerErrorMsg) );
}
void ClippingStation::saveClipImagesToFileServerWatcherFinished()
{
int id = m_saveClipImagesToFileServerWatcher.result();
if(id == 0) //if error happen, show a message
QMessageBox::critical(this, tr("Clipping Error"), tr("Error copying clipping images to file server (%1)").arg(saveClipImagesToFtpServerErrorMsg) );
//else
// Article::updateStatus(m_masterDatabase, id, 2);
}
void ClippingStation::addTextToClipWatcherFinished()
{
}
void ClippingStation::on_rejectButton_clicked()
{
//reject the current clip, i.e. set the reject value to 1.
//m_currentClipId;
QSqlQuery query(m_masterDatabase);
query.prepare("UPDATE article SET reject = 1 where id_article = :id");
query.bindValue(":id", m_currentClipId);
if( query.exec() )
{
//the clip is rejected, move it from the list
m_publication.currentIssue()->deleteArticleFromView(ui->clipsTreeView, m_currentClipId, false);
drawerResetPages();
//remove the cutouts
ui->fullpageView->removeImageCutouts();
}
}
void ClippingStation::thumbnail()
{
//first restore the page to its original size, then take the screenshot
if ( m_firstPageInClip.isEmpty() )
{
if (m_runningMode == PRECLIPPING_MODE ) m_firstPageInClip = m_preclippedLocalImagesList [m_preclippedImageIndex];
else if (m_runningMode == NORMAL_MODE ) m_firstPageInClip = m_localImagesList [m_imageIndex ];
else if (m_runningMode == CLIPPING_MODE ) m_firstPageInClip = m_clippedLocalImagesList [m_clippedImageIndex ];
}
QString currentPage;
if (m_runningMode == PRECLIPPING_MODE ) currentPage = m_preclippedLocalImagesList [m_preclippedImageIndex];
else if (m_runningMode == NORMAL_MODE ) currentPage = m_localImagesList [m_imageIndex ];
else if (m_runningMode == CLIPPING_MODE ) currentPage = m_clippedLocalImagesList [m_clippedImageIndex ];
if ( m_firstPageInClip == currentPage)
{
qreal oldscale = ui->fullpageView->actualSize();
QImage img = ui->fullpageView->screenShot();
ui->fullpageView->setScale(oldscale);
img = img.scaledToWidth(THUMBNAIL_WIDTH, Qt::SmoothTransformation);
m_thumbnail = img;
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(0));
view->addThumbnail(img);
}
}
void ClippingStation::createThumbnail()
{
thumbnail();
}
qreal ClippingStation::A4Scale()
{
int i = ui->stackedDrawerViewWidget->currentIndex();
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
m_currentA4Scale = view->currentScale();
return m_currentA4Scale;
}
void ClippingStation::enableDrawerButtons(bool enable)
{
ui->addPageButton ->setEnabled(enable);
ui->removePageButton ->setEnabled(enable);
ui->clipButton ->setEnabled(enable);
ui->rejectButton ->setEnabled(!enable);
}
void ClippingStation::setModifyClipButton(bool modify)
{
ui->clipButton->setEnabled(true);
if(modify)
ui->clipButton->setText(tr("Modify"));
else
ui->clipButton->setText(tr("Clip"));
}
void ClippingStation::setModifyPreclipButton(bool modify)
{
if(modify)
{
ui->preclipButton->setText(tr("Modify"));
ui->cancelModifyPreclipButton->setVisible(true);
}
else
{
ui->preclipButton->setText(tr("Preclip"));
ui->cancelModifyPreclipButton->setVisible(false);
}
}
void ClippingStation::cancelModifyPreclip()
{
qDebug("cancelModifyPreclip()");
setModifyPreclipButton(false);
loadImage();
}
void ClippingStation::loadFilteredPublication(int index)
{
if( index == 0 )
{
m_filterMode = NO_FILTER;
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
return;
}
else if( index == 1)
{
m_filterMode = PRECLIPSONLY_FILTER;
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
QStringList list = Publication::publicationsWithPreclips(m_slaveDatabase);
list.insert(0, "");
ui->preclippedPublicationComboBox->clear();
ui->preclippedPublicationComboBox->addItems(list);
}
else if(index == 2)
{
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
}
else if(index == 3)
{
m_filterMode = NO_FILTER;
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
QStringList list = Publication::publicationsWithUndoneIssues(m_slaveDatabase);
list.insert(0, "");
ui->undonePublicationComboBox->clear();
ui->undonePublicationComboBox->addItems(list);
}
}
void ClippingStation::loadClippingImages(int clipid)
{
qDebug("loadClippingImages()");
//get the number of a4 images for this clip, in addition to the path
QString path = SystemConfiguration::clippingsPath();
QStringList dateSplit = m_currentIssueDate.split("-");
path = path + QString("%1/%2/%3/").arg(dateSplit[0], 4, QChar('0')).arg(dateSplit[1], 2, QChar('0')).arg(dateSplit[2], 2, QChar('0'));
CURL *curlhandle = NULL; //the libcurl easy handle
if( m_useFtp)
{
path = QString("ftp://%1:%2@%3/").arg(m_username).arg(m_password).arg(m_address) + path;
curl_global_init(CURL_GLOBAL_ALL); //initate it
curlhandle = curl_easy_init();
}
else
{
#ifdef Q_WS_WIN
path = SystemConfiguration::clippingsWindowsDriveLetter() + path;
#endif
}
drawerResetPages();
int count = m_publication.currentIssue()->clip(clipid).imagesNumber(); //get number of clipped images
char str[255];
for(int i=0; i< count -1 ; i++) //add pages
drawerAddPage(false);
for(int i=0; i< count; i++)
{
QString tmpfilename = QString("%1-%2.jpg").arg(clipid).arg(i+1);
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
if(m_useFtp)
{
QString file = path+ tmpfilename;
if (!download(curlhandle, file.toLocal8Bit(), tmpfilename.toLocal8Bit(), 0, 3, str))
{
qDebug() << "loadClippingImages(): Error loading image " << file.toLocal8Bit() << ": " << str;
QMessageBox::critical(this, "error loading clip", QString("Ftp Error (%1) : %2").arg(file).arg(str) );
}
else
{
view->setPixmap(QPixmap(tmpfilename));
QFile::remove(tmpfilename);
}
}
else
{
QString fname = path+ tmpfilename;
view->setPixmap(QPixmap(fname));
}
}
ui->stackedDrawerViewWidget->setCurrentIndex(0);
updateDrawerPageInformation();
enableDrawerButtons(false);
setModifyClipButton(true);
}
int ClippingStation::totalNumberOfCutoutsInDrawer()
{
int count = 0;
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
count += view->cutoutsCount();
}
return count;
}
QStringList ClippingStation::emptyDrawerPages()
{
QStringList pages;
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
{
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
int count = view->cutoutsCount();
if(count == 0)
pages.append( QString("%1").arg(i+1) );
}
return pages;
}
void ClippingStation::orderCutoutsSelections()
{
ui->fullpageView->setOrderMode( ui->orderButton->isChecked() );
ui->preclipButton->setEnabled( !ui->orderButton->isChecked() );
ui->autoArrangeButton->setEnabled(!ui->orderButton->isChecked() );
}
void ClippingStation::addMargintoPos(QPointF &pos, bool isfirst)
{
int dpi = QApplication::primaryScreen()->logicalDotsPerInchX();
MarginValues mv;
if(isfirst)
mv = SystemConfiguration::firstPageMargin();
else
mv = SystemConfiguration::otherPagesMargin();
qreal left = mv.left * dpi / 2.54;
qreal top = mv.top * dpi / 2.54;
pos.setX( pos.x() + left );
pos.setY( pos.y() + top );
}
void ClippingStation::orderList(QList<ImageCutout*> &cutouts)
{
for(int i=0; i< cutouts.count() -1 ; i++)
{
int min = i;
for(int j=i+1 ; j< cutouts.count(); j++)
{
if(cutouts[min]->order() > cutouts[j]->order())
min = j;
}
if(min != i)
cutouts.swapItemsAt(i, min);
}
}
QSizeF ClippingStation::A4CellSize(bool isfirst)
{
// we compute pixels dimensions for the page.
int dpi = QApplication::primaryScreen()->logicalDotsPerInchX();
qreal pageWidth = dpi * A4_WIDTH;
qreal pageHeight = dpi * A4_HEIGHT;
MarginValues mv ;
if(isfirst)
mv = SystemConfiguration::firstPageMargin();
else
mv = SystemConfiguration::otherPagesMargin();
qreal m_top = mv.top * dpi / 2.54;
qreal m_bottom = mv.bottom * dpi / 2.54;
qreal m_left = mv.left * dpi / 2.54;
qreal m_right = mv.right * dpi / 2.54;
qreal w = pageWidth - (m_left + m_right);
qreal h = pageHeight - (m_top + m_bottom);
w /= 100.0;
h /= 100.0;
return QSizeF(w, h);
}
bool ClippingStation::calculatePosAndScale(QSizeF cellSize, QImage &img, int type, bool resetarray, QPointF &pos, qreal &scale)
{
#define CELLROWS 100
#define CELLCOLS 100
scale = 1.0;
static int cells[CELLROWS][CELLCOLS] = {0};
if(resetarray)
{
for(int j=0; j< CELLROWS; j++)
for(int i=0; i<CELLCOLS; i++)
cells[j][i] = 0;
}
//we try to find an open space with adjacent h and v cells
qreal minScale = 1.0;
if(type == BODY)
minScale = .9;
else
minScale = .4;
while(scale >= minScale)
{
qreal width = img.width() * scale;
qreal height= img.height()* scale;
qreal hw = width / cellSize.width();
qreal hl = height / cellSize.height();
qreal horizentalCells = ceil(hw);
qreal verticalCells = ceil(hl);
bool isArabic = (m_publication.language() == "Arabic");
if(isArabic)
{
for(int row =CELLROWS-1; row >=0; row--)
{
for(int col=0; col <CELLCOLS; col++)
{
//appropriate length
if(cells[row][col] == 0)
{
//check if we have the necessary cells to go thru
bool valid = true;
for(int i=0; i < verticalCells; i++)
{
if(col+i >= CELLCOLS)
{
valid = false;
break;
}
if(cells[row][col+i] == 0)
continue;
valid = false;
break;
}
if(!valid)
continue;
for(int i=0; i < horizentalCells; i++)
{
if(row+i >= CELLROWS)
{
valid = false;
break;
}
if(cells[row+i][col] == 0)
continue;
valid = false;
break;
}
if(!valid)
continue;
//now check the internal cells
for(int i=0; i<horizentalCells; i++)
{
for(int j=0; j < verticalCells; j++)
{
if(cells[row+i][col+j] != 0)
{
valid = false;
break;
}
}
}
if(!valid)
continue;
for(int i=0; i<horizentalCells; i++)
{
for(int j=0; j < verticalCells; j++)
cells[row+i][col+j] = 1;
}
/*
qDebug("After the settings of 1's");
for(int i=0; i<20; i++)
{
QString str;
for(int j=0; j< 20; j++)
str += QString("%1").arg(cells[i][j]) + " ";
qDebug() << str.toLocal8Bit();
}
qDebug("*****************************************************");
*/
//point would be
pos.setX(row*cellSize.width() );
pos.setY(col*cellSize.height());
return true;
}
}
}//end of for
}
else //not arabic
{
for(int row =0; row < CELLROWS; row++)
{
for(int col=0; col <CELLCOLS; col++)
{
//appropriate length
if(cells[row][col] == 0)
{
//check if we have the necessary cells to go thru
bool valid = true;
for(int i=0; i < verticalCells; i++)
{
if(col+i >= CELLCOLS)
{
valid = false;
break;
}
if(cells[row][col+i] == 0)
continue;
valid = false;
break;
}
if(!valid)
continue;
for(int i=0; i < horizentalCells; i++)
{
if(row+i >= CELLROWS)
{
valid = false;
break;
}
if(cells[row+i][col] == 0)
continue;
valid = false;
break;
}
if(!valid)
continue;
//now check the internal cells
for(int i=0; i<horizentalCells; i++)
{
for(int j=0; j < verticalCells; j++)
{
if(cells[row+i][col+j] != 0)
{
valid = false;
break;
}
}
}
if(!valid)
continue;
for(int i=0; i<horizentalCells; i++)
{
for(int j=0; j < verticalCells; j++)
cells[row+i][col+j] = 1;
}
/*
qDebug("After the settings of 1's");
for(int i=0; i<20; i++)
{
QString str;
for(int j=0; j< 20; j++)
str += QString("%1").arg(cells[i][j]) + " ";
qDebug() << str.toLocal8Bit();
}
qDebug("*****************************************************");
*/
//point would be
pos.setX(row*cellSize.width() );
pos.setY(col*cellSize.height());
return true;
}
}
}//end of for
}
scale -= .02;
}
return false;
}
bool ClippingStation::isImageLocked(QString image, int &lockedBy)
{
clock_t start = clock();
int id_publication = m_publication.id();
int id_issue = m_publication.currentIssue()->id();
int id_section = m_publication.currentIssue()->section(m_currentSectionName).id();
QFileInfo fi(image);
QString page_name = fi.fileName();
QSqlQuery query(m_slaveDatabase);
bool ret = query.exec("LOCK TABLES publication_issue as pub issue_sections as iss section_pages as sec READ");
query.prepare("SELECT locked_by FROM publication_issue as pub, issue_sections as iss, section_pages as sec WHERE "
" pub.id_publication_issue = iss.id_publication_issue AND "
" iss.id_issue_sections = sec.id_issue_sections AND "
" pub.id_publication = :id_publication AND "
" pub.id_issue = :id_issue AND "
" iss.id_section = :id_section AND "
" sec.page_name = :page_name");
query.bindValue(":id_publication", id_publication);
query.bindValue(":id_issue", id_issue);
query.bindValue(":id_section", id_section);
query.bindValue(":page_name", page_name);
if ( !query.exec() )
{
qDebug() << "isImageLocked() SQL query Error :" << query.lastError().databaseText().toLocal8Bit();
qDebug("%d\t%d\t%d", id_publication, id_issue, id_section);
qDebug() << page_name;
ret = query.exec("UNLOCK TABLES");
return false;
}
int user_id = 0;
if( query.next() )
user_id = query.value(0).toInt();
query.exec("UNLOCK TABLES");
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("isImageLocked() Time: %f", diff);
if(user_id != 0 && user_id != m_user.id() )
{
lockedBy = user_id;
return true;
}
return false;
}
bool ClippingStation::lockImage(QString image)
{
clock_t start = clock();
unlockImages();
int id_publication = m_publication.id();
int id_issue = m_publication.currentIssue()->id();
int id_section = m_publication.currentIssue()->section(m_currentSectionName).id();
int id_user = m_user.id();
QFileInfo fi(image);
QString page_name = fi.fileName();
QSqlQuery query(m_slaveDatabase);
bool ret = query.exec("LOCK TABLES publication_issue AS pub READ, section_pages AS sec WRITE, issue_sections AS iss READ");
query.prepare("UPDATE publication_issue as pub, issue_sections as iss, section_pages as sec "
" SET locked_by = :id_user "
" WHERE "
" pub.id_publication_issue = iss.id_publication_issue AND "
" iss.id_issue_sections = sec.id_issue_sections AND "
" pub.id_publication = :id_publication AND "
" pub.id_issue = :id_issue AND "
" iss.id_section = :id_section AND "
" sec.page_name = :page_name");
query.bindValue(":id_publication", id_publication);
query.bindValue(":id_issue", id_issue);
query.bindValue(":id_section", id_section);
query.bindValue(":page_name", page_name);
query.bindValue(":id_user", id_user);
ret = query.exec();
query.exec("UNLOCK TABLES");
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("lockImage() Time: %f", diff);
return ret;
}
bool ClippingStation::unlockImages()
{
clock_t start = clock();
int id_user = m_user.id();
QSqlQuery query(m_slaveDatabase);
query.exec("LOCK TABLE section_pages as sec WRITE");
query.prepare("UPDATE section_pages as sec "
" SET locked_by = 0 "
" WHERE "
" sec.locked_by = :id_user ");
query.bindValue(":id_user", id_user);
bool ret = query.exec();
query.exec("UNLOCK TABLES");
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("unlockImages() Time: %f", diff);
return ret;
}
int ClippingStation::getImageId(const QString name)
{
QSqlQuery query2(m_slaveDatabase);
query2.prepare("SELECT section_pages FROM "
" publication_issue as pub, issue_sections as iss, section_pages as sec "
" WHERE "
" pub.id_publication_issue = iss.id_publication_issue AND "
" iss.id_issue_sections = sec.id_issue_sections AND "
" pub.id_publication = :id_publication AND "
" pub.id_issue = :id_issue AND "
" iss.id_section = :id_section AND "
" sec.page_name = :page_name");
query2.bindValue(":id_publication", m_publication.id());
query2.bindValue(":id_issue", m_publication.currentIssue()->id() );
query2.bindValue(":id_section", m_publication.currentIssue()->section(m_currentSectionName).id() );
query2.bindValue(":page_name", name);
if ( !query2.exec() )
{
qDebug() << "Error in slave db query " << query2.lastQuery().toLocal8Bit();
qDebug() << "Error is " << query2.lastError().text();
return -1;
}
int id = 0;
while(query2.next() )
id = query2.value(0).toInt();
return id;
}
void ClippingStation::loadImageHighlights(int imageId)
{
clock_t start = clock();
QSqlQuery query(m_ocrDatabase);
query.prepare("SELECT id_company, coordinates, tag FROM "
" page_tag_coordinates "
" WHERE "
" id_section_pages = :id ");
query.bindValue(":id", imageId);
if ( !query.exec() )
{
qDebug() << "Error in ocr db query " << query.lastQuery().toLocal8Bit();
qDebug() << "Error is " << query.lastError().text();
return;
}
QList<TagCoordinates> tagH;
qDebug() << "retreive the results of page_tag_coordiantes";
while( query.next() )
{
int tagId = query.value(0).toInt();
QStringList coor = query.value(1).toString().split(":");
QStringList crd = coor[0].split(",");
int top = crd[0].toInt();
int left = crd[1].toInt();
int bottom =crd[2].toInt();
int right =crd[3].toInt();
QString tag = query.value(2).toString();
TagCoordinates t(tagId, top, left, bottom, right, tag);
for(int i=1; i< coor.count(); i++)
{
QStringList crd = coor[i].split(",");
int top = crd[0].toInt();
int left = crd[1].toInt();
int bottom =crd[2].toInt();
int right =crd[3].toInt();
//QRectF rec(QPointF(left, top), QPointF(right, bottom) );
//QPolygonF ply(rec);
//ui->fullpageView->createTagsHighlightes(ply);
t.AddCoordinates(top, left, bottom, right);
}
tagH.append(t);
}
qDebug() << "End get info from page_tag_coordinates" << Qt::endl;
//QTimer::singleShot(100, this, SLOT(addRelatedKeywordsToTag(tagH)));
//we add the name to the tags
/*QSqlQuery query2(m_slaveDatabase);
query2.prepare("SELECT name_company FROM company AS cm, searchword AS sw "
" WHERE name_searchword LIKE :name1 AND sw.id_company = cm.id_company AND cm.date_end > NOW() "
" UNION SELECT name_company FROM company WHERE name_company LIKE :name2 AND date_end > NOW()");
for(int i=0; i< tagH.count(); i++)
{
qDebug() << "Searching for tag: " << tagH[i].tag();
query2.bindValue(":name1", tagH[i].tag() );
query2.bindValue(":name2", tagH[i].tag() );
if(query2.exec())
{
QStringList keywords;
while(query2.next())
{
QString name = query2.value(0).toString();
qDebug() << "related tag: " << name;
keywords.append(name);
}
qDebug() << "for tag " << tagH[i].tag() << ", the number of related keyword is " << keywords.count();
tagH[i].setRelatedKeywords(keywords);
}
}*/
ui->fullpageView->addTagCoordinates(tagH);
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("loadImageHighlights() Time: %f", diff);
}
void ClippingStation::addRelatedKeywordsToTag(QList<TagCoordinates> &tagH)
{
qDebug() << "addRelatedKeywordsToTag()";
QSqlQuery query2(m_slaveDatabase);
query2.prepare("SELECT name_company FROM company AS cm, searchword AS sw "
" WHERE name_searchword LIKE :name1 AND sw.id_company = cm.id_company AND cm.date_end > NOW() "
" UNION SELECT name_company FROM company WHERE name_company LIKE :name2 AND date_end > NOW()");
for(int i=0; i< tagH.count(); i++)
{
qDebug() << "Searching for tag: " << tagH[i].tag();
query2.bindValue(":name1", tagH[i].tag() );
query2.bindValue(":name2", tagH[i].tag() );
if(query2.exec())
{
QStringList keywords;
while(query2.next())
{
QString name = query2.value(0).toString();
qDebug() << "related tag: " << name;
keywords.append(name);
}
qDebug() << "for tag " << tagH[i].tag() << ", the number of related keyword is " << keywords.count();
tagH[i].setRelatedKeywords(keywords);
}
}
ui->fullpageView->addTagCoordinates(tagH);
qDebug() << "end of addRelatedKeywordsToTag()";
}
QList<WordCoordinates> ClippingStation::loadImageText(QString page, QSqlDatabase &database)
{
qDebug() << "loadImageText(QString page, QSqlDatabase &database)";
clock_t start = clock();
QStringList list = page.split("/");
QString id_issue = list[list.count()-6] + list[list.count()-5]+ list[list.count()-4];
QString page_name = list[list.count()-1];
int id_section = list[list.count()-2].toInt();
int id_publication = list[list.count()-3].toInt();
QSqlQuery query(database);
query.prepare("SELECT section_pages FROM "
" publication_issue as pub, issue_sections as iss, section_pages as sec "
" WHERE "
" pub.id_publication_issue = iss.id_publication_issue AND "
" iss.id_issue_sections = sec.id_issue_sections AND "
" pub.id_publication = :id_publication AND "
" pub.id_issue = :id_issue AND "
" iss.id_section = :id_section AND "
" sec.page_name = :page_name");
query.bindValue(":id_publication", id_publication);
query.bindValue(":id_issue", id_issue );
query.bindValue(":id_section", id_section );
query.bindValue(":page_name", page_name);
int section_pages = 0;
QList<WordCoordinates> tagW;
if (!query.exec())
{
qDebug() << query.lastError().text().toLocal8Bit();
return tagW;
}
if(query.next())
section_pages = query.value(0).toInt();
QSqlQuery query2(m_ocrDatabase);
query2.prepare("SELECT word, coordinates FROM "
" page_word_coordinates"
" WHERE "
" id_section_pages = :id "
" order by id_page_word_coordinates");
query2.bindValue(":id", section_pages);
if ( !query2.exec() )
{
qDebug() << query2.lastError().text().toLocal8Bit();
return tagW;
}
while( query2.next() )
{
QString word = query2.value(0).toString();
qDebug() << "word is " << word;
QStringList coor = query2.value(1).toString().split(":");
QStringList crd = coor[0].split(",");
int top = crd[0].toInt();
int left = crd[1].toInt();
int bottom =crd[2].toInt();
int right =crd[3].toInt();
WordCoordinates t(word, top, left, bottom, right);
tagW.append(t);
}
//ui->fullpageView->addWordCoordinates(tagW);
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
qDebug("loadImageText() Time: %f", diff);
return tagW;
}
void ClippingStation::addTagsToTagWrapper(QList<int> &tagIds, QStringList tagCoord, bool removedAndThenAdd)
{
QList<Tag> tags = Tag::searchTags(m_slaveDatabase, tagIds);
for(int i=0; i< tags.count(); i++)
{
if(tags[i].id() == tagIds[i])
tags[i].setCoordinates(tagCoord[i]);
}
if(removedAndThenAdd)
m_tagsWrapper.removedOcrTags(tags);
else
m_tagsWrapper.appenedOcrTags(tags);
m_tagsWrapper.showModel();
}
void ClippingStation::updateSectionPagesStatus()
{
QAbstractItemModel* model = ui->issuesTreeView->model();
int issuesCount = model->rowCount( QModelIndex() );
for(int i=0; i< issuesCount; i++)
{
if(m_currentIssueDate.isEmpty())
return;
QString issue = model->index(i, 0, QModelIndex() ).data(Qt::DisplayRole).toString();
if(issue != m_currentIssueDate) //get current issue
continue;
QModelIndex issueIndex = model->index(i, 0, QModelIndex() );
int sectionsCount = model->rowCount(issueIndex);
for(int j=0; j < sectionsCount; j++)
{
//get pages status for this particular section from database.
//the data is returned as mab (name, status);
QString section = model->index(j, 0, issueIndex).data(Qt::DisplayRole).toString();
int sectionId = m_publication.currentIssue()->section(section).id();
QHash<QString, QIcon> hash = currentSectionPagesStatus(sectionId);
QModelIndex sectionIndex = model->index(j, 0, issueIndex);
int pagesCount = model->rowCount(sectionIndex);
for(int k=0; k< pagesCount; k++)
{
QString pageName = model->index(k, 0, sectionIndex).data(Qt::DisplayRole).toString();
pageName = QString("%1.jpg").arg(pageName.remove(QRegularExpression("[^\\d]")), 4, QChar('0'));
QModelIndex pageIndex = model->index(k, 0, sectionIndex);
if( hash.find(pageName) != hash.end() )
model->setData(pageIndex, QVariant(hash[pageName]) , Qt::DecorationRole);
}
}
}
}
QHash<QString, QIcon> ClippingStation::currentSectionPagesStatus(int sectionId)
{
QHash<QString, QIcon> hash;
QSqlQuery query(m_masterDatabase);
query.prepare("SELECT id_issue_sections FROM issue_sections, publication_issue "
"WHERE publication_issue.id_publication_issue = issue_sections.id_publication_issue AND "
"id_publication = :id_publication AND issue_date = :issue_date AND id_section = :id_section");
query.bindValue(":id_publication", m_publication.id() );
query.bindValue(":issue_date", m_publication.currentIssue()->date() );
query.bindValue(":id_section", sectionId);
if(! query.exec() )
return hash;
int id_issue_sections = 0;
if( query.next())
id_issue_sections = query.value(0).toInt();
query.exec("LOCK TABLE section_pages READ");
query.prepare("SELECT page_name, status FROM section_pages "
"WHERE id_issue_sections = :id_issue_sections ORDER BY page_name");
query.bindValue(":id_issue_sections", id_issue_sections);
if ( !query.exec() )
{
query.exec("UNLOCK TABLES");
return hash;
}
while ( query.next() )
{
QString filename = query.value(0).toString();
int status = query.value(1).toInt();
QIcon icon;
if(status < 1) //not processed
icon.addFile(":/icons/no_icon.png");
else if (status == 1 ) //waiting to be processed
icon.addFile(":/icons/gray_circle.png");
else if (status == 2 ) //being procssed
icon.addFile(":/icons/yellow_circle.png");
else //finished processing
icon.addFile(":/icons/green_circle.png");
hash.insert(filename, icon);
}
query.exec("UNLOCK TABLES");
return hash;
}
void ClippingStation::filterPublications()
{
if(m_searchPublicationsDlg.exec() == QDialog::Accepted )
{
//get the values from the
QString keyword, startDate, endDate, type, country, ocrSearchword, status;
bool ischecked;
m_searchPublicationsDlg.get(keyword, ischecked, startDate, endDate, type, country, ocrSearchword, status);
//now search for the publications that meet those criteria
int countryId = -1;
if(!country.isEmpty())
countryId = m_countriesHash[country];
int typeId = -1;
if(!type.isEmpty())
{
if(type.compare("newspaper", Qt::CaseInsensitive) == 0) //NEWSPAPER 1
typeId = 1;
else if(type.compare("magazine", Qt::CaseInsensitive) == 0)
typeId = 2;
}
QStringList list = m_publication.publicationsFiltered(m_slaveDatabase, m_ocrDatabase, keyword, startDate, endDate, typeId, countryId, ocrSearchword, status);
list.insert(0, "");
ui->filteredPublicationComboBox->clear();
ui->filteredPublicationComboBox->addItems(list);
}
}
void ClippingStation::setShortcuts()
{
if( !m_clipShortcut.isEmpty() )
ui->actionClip->setShortcut(m_clipShortcut);
if( !m_preclipShortcut.isEmpty() )
ui->actionPreclip->setShortcut(m_preclipShortcut);
if( !m_addPageShortcut.isEmpty() )
ui->actionDrawerAddPage->setShortcut(m_addPageShortcut);
if( !m_nextPageShortcut.isEmpty() )
ui->actionNextPage->setShortcut(m_nextPageShortcut);
if( !m_previousPageShortcut.isEmpty() )
ui->actionPreviousPage->setShortcut(m_previousPageShortcut);
}
void ClippingStation::pauseTracking()
{
if(m_currentPageId <= 0)
return;
if(m_isPaused)
{
//resume
ui->fullpageView->setImageVisibility(true);
m_trackingTimer.start(1000);
ui->pauseTrackButton->setText(tr("Pause Tracking"));
m_isPaused = false;
}
else
{
ui->fullpageView->setImageVisibility(false);
m_trackingTimer.stop();
ui->pauseTrackButton->setText(tr("Resume Tracking"));
m_isPaused = true;
}
}
void ClippingStation::updateTrackLabel()
{
ui->lcdCounter->showTime(++m_trackingSeconds);
if((m_trackingSeconds % m_maxTimeLimit) == 0)
{
if(!m_isPaused)
pauseTracking();
}
}
int ClippingStation::publicationIssueId(int id_publication, QString issue_date)
{
QSqlQuery query(m_slaveDatabase);
query.prepare("SELECT id_publication_issue FROM publication_issue "
"WHERE id_publication = :id_publication AND issue_date = :issue_date");
query.bindValue(":id_publication", id_publication);
query.bindValue(":issue_date", issue_date);
if(!query.exec())
{
qDebug() << "select id_publication_issue query error: " << query.lastError().text();
qDebug() << "returning 0";
return 0;
}
int id_publication_issue = 0;
if(query.next())
{
id_publication_issue = query.value(0).toInt();
return id_publication_issue;
}
return id_publication_issue;
}
int ClippingStation::issueSectionsId(int id_publication_issue, int id_section)
{
QSqlQuery query(m_slaveDatabase);
query.prepare("SELECT id_issue_sections FROM issue_sections WHERE "
"id_publication_issue = :id_publication_issue AND id_section = :id_section");
query.bindValue(":id_publication_issue", id_publication_issue);
query.bindValue(":id_section", id_section);
if ( !query.exec() )
{
qDebug() << "select id_issue_sections query error: " << query.lastError().text();
qDebug() << "returning 0";
return 0;
}
int id_issue_sections = 0;
if( query.next() )
id_issue_sections = query.value(0).toInt();
return id_issue_sections;
}
QStringList ClippingStation::getRelatedKeywords(QString tag)
{
QSqlQuery query2(m_slaveDatabase);
query2.prepare("SELECT name_company FROM company AS cm, searchword AS sw "
" WHERE name_searchword LIKE :name1 AND sw.id_company = cm.id_company AND cm.date_end > NOW() "
" UNION SELECT name_company FROM company WHERE name_company LIKE :name2 AND date_end > NOW()");
qDebug() << "Searching for tag: " << tag;
query2.bindValue(":name1", tag );
query2.bindValue(":name2", tag );
QStringList keywords;
if(query2.exec())
{
while(query2.next())
{
QString name = query2.value(0).toString();
qDebug() << "related tag: " << name;
keywords.append(name);
}
qDebug() << "for tag " << tag << ", the number of related keyword is " << keywords.count();
}
return keywords;
}
void ClippingStation::onAppFocusChanged()
{
if(m_currentPageId <= 0) //no pages has been opened yet
return;
if(QApplication::focusWidget())
{
if(m_isPaused) //if its pause, return without doing anything
return;
ui->fullpageView->setImageVisibility(true);
m_trackingTimer.start(1000);
}
else
{
ui->fullpageView->setImageVisibility(false);
m_trackingTimer.stop();
}
}