MediaMonkey / Aplicativos

Fórum sobre interface com o Cliente.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Continuo usando o MediaMonkey pra músicas.
Mas continuo olhando de outra forma....
mediamonkey.png
Em destaque o recurso de lista automática.
Esse recurso é só com a versão paga, ou com crack.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

auto1.png
Configuração de filtros, configuração de ordem, configuração de limites.
Detalhe no filtro: pode ser CADA um individual, ou TODOS ao mesmo tempo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

auto2.png
CADA filtro, tem lá o campo referência, o tipo de análise a ser feita, e com o que vai ser comparado.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Pra curiosidade:

Tem a opção AUTO DJ, que automaticamente adiciona músicas pra tocar.
Configurei pra selecionar 5 músicas dessa lista "Play List", é feita uma escolha randômica.

A PLaylist:

Ela busca, em todas as músicas, em ordem das que defini como melhores, e mais tocadas, num limite de 100 músicas.
100 músicas, aprox. 5 minutos cada, a lista inicial atende mais de um dia de música.

A lista não considera execuções multiplas de 5, significa que uma música tocada 5 vezes, ou 10 vezes, sai da lista.
Se deixar assim eternamente, vai acabar tocando todas as músicas, 5 vezes cada uma e parar.

Ainda assim, a ordem principal é de "pulos". Se pular uma música, ela vai pro fim da fila geral, quanto mais pular, mais pro fim da fila ela vai. Fim da fila significa que se tem 2.000 músicas, precisa tocar 1900 músicas 5 vezes, pra chegar nas 100 últimas, onde talvez ela seja a próxima.

As múltiplas de 5.... se eu quiser que entre na fila novamente, é só acrescentar na lista.
Supondo que sejam 5 execuções, ao tocar mais uma vez, aumenta pra 6 e entra na lista até trocar 10 vezes.

É tudo automático, basta ficar ouvindo música, pular alguma, ou repetir alguma que tocou 5 vezes.

Uma lista das piores pode ser as mais puladas e menos tocadas... candidatas pra exclusão.
A gente acaba sempre guardando clássicas, por serem clássicas e não porque gostamos de ouvir toda hora....

Já cheguei a ter mais de 50.000 músicas, mas hoje tem só cerca de 2.000, e mesmo assim, várias são porque meu filho é quem gosta.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Bom....
Agora vamos ao que interessa.

E uma coisa assim no aplicativo?
Isso pode ser considerado como um gerador de relatórios, totalmente definido pelo usuário.
Ele vai ter resumos do jeito que ele quer/precisa, prontos para uso.

Estou começando a olhar essa lista do MediaMonkey por este ponto de vista.

Só pra lembrar: o MediaMonkey usa SQLite3 e comandos SQL, é isso que deixa tudo flexível.
Mas é lógico... escolher músicas não dá pra comparar com escolher informações do aplicativo... mas é pra pensar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Não achei minha postagem da outra vez, mas um parecido que fiz foi este.
Infelizmente, está um pouco preso ao meu aplicativo, está nas opções de teste.
Deixo a maioria das coisas assim, porque minha pasta temporária é limpa automaticamente, com qualquer teste que eu faça lá....

Código: Selecionar todos

/*
PTESFILTRO - Teste do filtro automatico
José Quintas
*/

#include "hbclass.ch"
#include "inkey.ch"
#define FIELD_NAME       1
#define FIELD_COMPARE    2
#define FIELD_SELECTED   3
#define FIELD_RANGEFROM  4
#define FIELD_RANGETO    5
// Until 8, to define list

#define COMPARE_NO_FILTER          1 //
#define COMPARE_EQUAL              2 // =
#define COMPARE_GREATHER_OR_EQUAL  3 // >=
#define COMPARE_LESS_OR_EQUAL      4 // <=
#define COMPARE_GREATHER           5 // >
#define COMPARE_LESS               6 // <
#define COMPARE_NOT_EQUAL          7 // !=
#define COMPARE_RANGE              8 // >= rangefrom .AND. <= rangeto
#define COMPARE_HAS_TEXT           9 // text $ field
#define COMPARE_NOT_HAS_TEXT      10 // ! text $ field
#define COMPARE_BEGIN_WITH_TEXT   11 // field = text*
#define COMPARE_IN_TEXT           12 // field $ text
#define COMPARE_NOT_IN_TEXT       13 // ! field $ text

MEMVAR acFields

PROCEDURE PTESFILTRO

   LOCAL oFilter

   IF ! AbreArquivos( "jpctplano" )
      RETURN
   ENDIF
   oFilter := FilterClass():New()
   oFilter:Execute()
   CLOSE DATABASES

   RETURN

CREATE CLASS FilterClass

   VAR    acFilterConfig   INIT {}
   METHOD Init()
   METHOD Filter()                                 // filter result
   METHOD FilterAsString()                         // an string with filter to be displayed
   METHOD FilterOptionsAsArray( lIncludeAll )      // an array to use as options to select
   METHOD FilterOptions()                          // an array with filter types
   METHOD Show( nRowi, nColi, nRowf, nColf )       // diplay filter string
   METHOD ChooseFilter()                           // user select filter options
   METHOD SelectFields()
   METHOD GetFieldFilter( nOpcCompare, nFieldCompare, xFieldIni, xFieldEnd )
   METHOD Execute()
   METHOD Browse( nTop, nLeft, nBottom, nRight )

   ENDCLASS

METHOD Init() CLASS FilterClass

   LOCAL acStru, nCont, xValue

   acStru := dbStruct()
   FOR nCont = 1 TO Len( acStru )
      xValue := EmptyValue( FieldGet( nCont ) )
      Aadd( ::acFilterConfig, { FieldName( nCont ), COMPARE_NO_FILTER, .F., xValue, xValue, xValue, xValue, xValue } )
   NEXT

   RETURN NIL

METHOD Filter() Class FilterClass

   LOCAL oElement, lReturn := .T., xValue

   FOR EACH oElement IN ::acFilterConfig
      xValue := FieldGet( FieldPos( oElement[ FIELD_NAME ] ) )
      DO CASE
      CASE oElement[ FIELD_COMPARE ] == COMPARE_NO_FILTER
      CASE oElement[ FIELD_COMPARE ] == COMPARE_EQUAL ;             lReturn := ( xValue == oElement[ FIELD_RANGEFROM ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_GREATHER_OR_EQUAL ; lReturn := ( xValue >= oElement[ FIELD_RANGEFROM ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_LESS_OR_EQUAL ;     lReturn := ( xValue <= oElement[ FIELD_RANGEFROM ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_GREATHER ;          lReturn := ( xValue >  oElement[ FIELD_RANGEFROM ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_LESS ;              lReturn := ( xValue <  oElement[ FIELD_RANGEFROM ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_NOT_EQUAL ;         lReturn := ( xValue != oElement[ FIELD_RANGEFROM ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_RANGE ;             lReturn := ( xValue >= oElement[ FIELD_RANGEFROM ] .AND. xValue <= oElement[ FIELD_RANGETO ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_HAS_TEXT ;          lReturn := ( Trim( oElement[ FIELD_RANGEFROM ] ) $ xValue )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_NOT_HAS_TEXT ;      lReturn := ( ! Trim( oElement[ FIELD_RANGEFROM ] ) $ xValue )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_BEGIN_WITH_TEXT ;   lReturn := ( Substr( xValue, 1, Len( Trim( oElement[ FIELD_RANGEFROM ] ) ) ) == Trim( oElement[ FIELD_RANGEFROM ] ) )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_IN_TEXT;            lReturn := ( xValue $ oElement[ FIELD_RANGEFROM ] )
      CASE oElement[ FIELD_COMPARE ] == COMPARE_NOT_IN_TEXT;        lReturn := ( ! xValue $ oElement[ FIELD_RANGEFROM ] )
      ENDCASE
      IF ! lReturn
         EXIT
      ENDIF
   NEXT

   RETURN lReturn

METHOD FilterAsString() CLASS FilterClass

   LOCAL xValue, oElement

   xValue := ""
   FOR EACH oElement IN ::acFilterConfig
      IF oElement[ FIELD_COMPARE ] != COMPARE_NO_FILTER
         xValue += oElement[ FIELD_NAME ] + " "
         xValue += ::FilterOptions()[ oElement[ FIELD_COMPARE ] ] + " "
         IF oElement[ FIELD_COMPARE ] == COMPARE_RANGE
            xValue += Trim( Transform( oElement[ FIELD_RANGEFROM ], "" ) ) + " to "
            xValue += Trim( Transform( oElement[ FIELD_RANGETO ], "" ) )
         ELSE
            xValue += Trim( Transform( oElement[ FIELD_RANGEFROM ], "" ) )
         ENDIF
         xValue += ", "
      ENDIF
   NEXT

   RETURN xValue

METHOD FilterOptionsAsArray( lIncludeAll ) CLASS FilterClass

   LOCAL xValue, acTxtFiltros := {}, oElement

   hb_Default( @lIncludeAll, .T. )
   FOR EACH oElement IN ::acFilterConfig
      xValue := oElement[ FIELD_NAME ] + " "
      IF oElement[ FIELD_COMPARE ] == COMPARE_NO_FILTER
         xValue += " No Filter "
      ELSE
         xValue += ::FilterOptions()[ oElement[ FIELD_COMPARE ] ] + " "
         IF oElement[ FIELD_COMPARE ] == COMPARE_RANGE
            xValue += Trim( Transform( oElement[ FIELD_RANGEFROM ], "" ) ) + " to " + xValue + Trim( Transform( oElement[ FIELD_RANGETO ], "" ) )
         ELSE
            xValue += Trim( Transform( oElement[ FIELD_RANGEFROM ], "" ) )
         ENDIF
      ENDIF
      IF oElement[ FIELD_COMPARE ] != COMPARE_NO_FILTER .OR. lIncludeAll
         Aadd( acTxtFiltros, xValue )
      ENDIF
   NEXT

   RETURN acTxtFiltros

METHOD FilterOptions() CLASS FilterClass

   LOCAL xValue := { "No Filter", "equal", "Greather or Equal", "Less or Equal", "Greather", "Less", "Not Equal", "Range", "Have Text", "Haven't Text", "Begin With", "In Text", "Not In Text" }

   RETURN xValue

METHOD Show( nRowi, nColi, nRowf, nColf ) CLASS FilterClass

   LOCAL cText, nLen, nCont

   nLen := nColf - nColi + 1
   cText := ::FilterAsString()
   FOR nCont = nRowi TO nRowf
      @ nCont, nColi SAY Substr( cText, ( nCont - nRowi ) * nLen + 1, nLen )
   NEXT

   RETURN NIL

METHOD ChooseFilter() CLASS FilterClass

   LOCAL nOpcField := 1, nOpcCompare, nCont, acTxtActive, nOpcActive := 1, lOk, oElement

   wOpen( 5, 0, 20, 80, "Filter" )
   DO WHILE .t.
      acTxtActive := ::FilterOptionsAsArray( .f. )
      aSize( acTxtActive, Len( acTxtActive ) + 4 )
      FOR nCont = 1 TO 4
         AIns( acTxtActive, 1 )
      NEXT
      acTxtActive[ 1 ] := "Select Fields"
      acTxtActive[ 2 ] := "Finish Filter"
      acTxtActive[ 3 ] := "Change Filter"
      acTxtActive[ 4 ] := "Reset"
      nOpcActive := Min( nOpcActive, Len( acTxtActive ) )
      Scroll( 7, 1, 19, 79, 0 )
      Achoice( 7, 1, 19, 79, acTxtActive, .t. ,,@nOpcActive )
      DO CASE
      CASE LastKey() == K_ESC
         EXIT
      CASE nOpcActive == 1
         ::SelectFields()
         LOOP
      CASE nOpcActive == 2
         lOk := .F.
         FOR EACH oElement IN ::acFilterConfig
            IF oElement[ FIELD_SELECTED ]
               lOk := .T.
               EXIT
            ENDIF
         NEXT
         IF ! lOk
            Alert( "If you do not select fields, no filter to show" )
            LOOP
         ENDIF
         EXIT
      CASE nOpcActive == 4
         FOR EACH oElement IN ::acFilterConfig
            oElement[ FIELD_COMPARE ] := COMPARE_NO_FILTER
         NEXT
         LOOP
      ENDCASE
      wOpen( 5, 0, 20, 80, "Field To Filter" )
      DO WHILE .t.
         Achoice( 7, 1, 19, 79, ::FilterOptionsAsArray(), .t.,, @nOpcField )
         IF LastKey() == K_ESC
            EXIT
         ENDIF
         wOpen( 6, 10, 20, 60, "Filter Type" )
         DO WHILE .t.
            Achoice( 8, 11, 19, 59, ::FilterOptions, .t.,, @nOpcCompare )
            IF LastKey() == K_ESC
               EXIT
            ENDIF
            ::GetFieldFilter( nOpcCompare, ;
               @::acFilterConfig[ nOpcField, FIELD_COMPARE ], ;
               @::acFilterConfig[ nOpcField, FIELD_RANGEFROM ], ;
               @::acFilterConfig[ nOpcField, FIELD_RANGETO ] )
            EXIT
         ENDDO
         wClose()
      ENDDO
      wClose()
   ENDDO
   wClose()

   RETURN LastKey() != K_ESC

METHOD SelectFields() CLASS FilterClass

   LOCAL oElement
   PRIVATE acFields := {}

   FOR EACH oElement IN ::acFilterConfig
      AAdd( acFields, iif( oElement[ FIELD_SELECTED ], "*", " " ) + " " + oElement[ FIELD_NAME ] )
   NEXT
   wOpen( 7, 10, 20, 80, "Select Fields" )
   AChoice( 8, 11, 19, 79, acFields, "", { | ... | UDFSelectField( ... ) } )
   wClose()
   FOR EACH oElement IN acFields
      ::acFilterConfig[ oElement:__EnumIndex, FIELD_SELECTED ] := ( Left( oElement, 1 ) == "*" )
   NEXT

   RETURN NIL

METHOD GetFieldFilter( nOpcCompare, nFieldCompare, xFieldIni, xFieldEnd ) CLASS FilterClass

   LOCAL GetList := {}

   DO CASE
   CASE nOpcCompare == COMPARE_NO_FILTER
      nFieldCompare := nOpcCompare
   CASE nOpcCompare == COMPARE_RANGE
      nFieldCompare := nOpcCompare
      wOpen( 10, 20, 16, 80, "From/To" )
      SetColor( "W/B,N/W,,,W/B" )
      IF ValType( xFieldIni ) == "C"
         IF Len( xFieldIni ) > 48
            @ 12, 22 GET xFieldIni PICTURE "@!S 48"
            @ 14, 22 GET xFieldEnd PICTURE "@!S 48"
         ELSE
            @ 12, 22 GET xFieldIni PICTURE "@!"
            @ 14, 22 GET xFieldEnd PICTURE "@!"
         ENDIF
      ELSE
         @ 12, 22 GET xFieldIni
         @ 14, 22 GET xFieldEnd
      ENDIF
      READ
      wClose()
   CASE nOpcCompare == COMPARE_HAS_TEXT .OR. nOpcCompare == COMPARE_NOT_HAS_TEXT .OR. nOpcCompare == COMPARE_BEGIN_WITH_TEXT
      IF ValType( xFieldIni ) != "C"
         Alert( "Valid only for String" )
      ELSE
         wOpen( 10, 20, 15, 80, "Value To Compare" )
         nFieldCompare := nOpcCompare
         SetColor( "W/B,N/W,,,W/B" )
         @ 12, 22 GET xFieldIni PICTURE "@!"
         READ
         wClose()
      ENDIF
   OTHERWISE
      nFieldCompare := nOpcCompare
      wOpen( 10, 20, 15, 80, "Value To Compare" )
      SetColor( "W/B,N/W,,,W/B" )
      IF ValType( xFieldIni ) == "C"
         @ 12, 22 GET xFieldIni PICTURE "@!"
      ELSE
         @ 12, 22 GET xFieldIni
      ENDIF
      READ
      wClose()
   ENDCASE

   RETURN NIL

METHOD Execute() CLASS FilterClass

   LOCAL nQtdRec

   DO WHILE .T.
      IF ! ::ChooseFilter()
         EXIT
      ENDIF
      SET FILTER TO ::Filter()
      COUNT TO nQtdRec
      SetColor( SetColorNormal() )
      @ 1, 0 SAY "Records in Filter:" + Str( nQtdRec )
      ::Show( MaxRow() - 2, 0, MaxRow(), MaxCol() )
      ::Browse( 2, 0, MaxRow() - 4, MaxCol() )
      SET FILTER TO
   ENDDO

   RETURN NIL

METHOD Browse( nTop, nLeft, nBottom, nRight ) CLASS FilterClass

   LOCAL oBrowse, oElement, nKey

   oBrowse := tBrowseDb( nTop, nLeft, nBottom, nRight )
   FOR EACH oElement IN ::acFilterConfig
      IF oElement[ FIELD_SELECTED ]
         oBrowse:AddColumn( TBColumnNew( oElement[ FIELD_NAME ], FieldBlock( oElement[ FIELD_NAME ] ) ) )
      ENDIF
   NEXT
   GOTO TOP
   DO WHILE .T.
      DO WHILE ! oBrowse:Stable
         oBrowse:Stabilize()
      ENDDO
      nKey := Inkey(0)
      IF nKey == K_ESC
         EXIT
      ENDIF
      oBrowse:ApplyKey( nKey )
   ENDDO
   Scroll( nTop, nLeft, nBottom, nRight, 0 )

   RETURN NIL

STATIC FUNCTION UDFSelectField( nModo, nElemento, nSelecao )   // Used in METHOD SelectFields()

   IF LastKey() == K_SPACE
      acFields[ nElemento ] := iif( Left( acFields[ nElemento ], 1 ) == "*", " ", "*" ) + Substr( acFields[ nElemento ], 2 )
   ELSEIF LastKey() == K_ESC .OR. Lastkey() == K_ENTER
      RETURN 0
   ENDIF
   HB_SYMBOL_UNUSED( nModo + nSelecao )

   RETURN 2
Basicamente é abrir um arquivo e chamar o filtro.
Dá pra escolher os campos, e escolher os filtros pra cada campo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Não sobrou quase nenhum DBF pra teste, só o contábil mesmo.

menu principal
filtro1.png
primeira opção: escolher quais os campos vão aparecer
filtro2.png
encerrou, é o browse
filtro3.png
pode escolher um campo pra filtro
filtro4.png
por exemplo, o filtro de/até
filtro5.png
o filtro igual
filtro6.png
Encerrou a configuração, aparece do jeito que escolheu.

É parecido com o do MediaMonkey, só não o mesmo visual.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Uma diferença básica é que neste é apenas um tipo de filtro por campo.
Pra ficar igual, teria que criar outro array, com cada filtro que for feito, permitindo o mesmo campo várias vezes.
Nem seria complicado, é exatamente o array que tem hoje, que ficaria isolado dos campos.
Talvez a seleção do filtro fique mais fácil, ou talvez a mesma coisa.

Vou tentar criar isso, por enquanto só como curiosidade/desafio.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Seria a mesma coisa, só trocar o achoice por PROMPT talvez, ou por abrir uma janela, já que não tem combobox em console.

Código: Selecionar todos

      wOpen( 5, 0, 20, 80, "Field To Filter" )
      DO WHILE .t.
         Achoice( 7, 1, 19, 79, ::FilterOptionsAsArray(), .t.,, @nOpcField )
         IF LastKey() == K_ESC
            EXIT
         ENDIF
         wOpen( 6, 10, 20, 60, "Filter Type" )
         DO WHILE .t.
            Achoice( 8, 11, 19, 59, ::FilterOptions, .t.,, @nOpcCompare )
            IF LastKey() == K_ESC
               EXIT
            ENDIF
            ::GetFieldFilter( nOpcCompare, ;
               @::acFilterConfig[ nOpcField, FIELD_COMPARE ], ;
               @::acFilterConfig[ nOpcField, FIELD_RANGEFROM ], ;
               @::acFilterConfig[ nOpcField, FIELD_RANGETO ] )
            EXIT
         ENDDO
         wClose()
      ENDDO
      wClose()
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Pra quem não entendeu, algo do tipo:

Código: Selecionar todos

@ 2, 0 PROMPT Campo[ 1 ]
@ 2, 0 PROMPT Campo[ 2 ]
@ 2, 0 PROMPT Campo[ 3 ]
MENU TO nOpcCampo
@ 4, 0 PROMPT TIpo[ 1 ]
@ 4, 0 PROMPT Tipo[ 2 ]
@ 4, 0 PROMPT Tipo[ 3 ]
MENU TO nOpcTipo
Isso vai deixar só a opção escolhida em destaque, e vai permitir alterar pelas setas.
Acaba até deixando a tela mais limpa.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Olhem aí um teste rápido, como ficou mais limpo:

Código: Selecionar todos

      wOpen( 5, 0, 20, 80, "Filter" )
      FOR EACH oElement IN ::acFilterConfig
         @ 7, 1 PROMPT Pad( oElement[ FIELD_NAME ], 20 )
      NEXT
      MENU TO nOpcField
      FOR EACH oElement IN ::FilterOptions
         @ 9, 1 PROMPT Pad( oElement, 20 )
      NEXT
      MENU TO nOpcCompare
      @ 11, 1 GET ::acFilterConfig[ nOpcField, FIELD_COMPARE ]
      @ 12, 1 GET ::acFilterConfig[ nOpcField, FIELD_RANGEFROM ]
      @ 13, 1 GET ::acFilterConfig[ nOpcField, FIELD_RANGETO ]
      READ
      wClose()
filtro1.png
filtro1.png (9.34 KiB) Exibido 7044 vezes
Nem dá pra perceber o PROMPT/array, porque é tudo numa mesma posição.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

To apanhando um pouco pra alterar, mas tá relativamente mais fácil que antes.

Sério, não é um bicho do outro mundo.

Agora tenho duas listas:

Campos: contendo nome, .T. ou .F. se é pra aparecer, e um valor zerado

Filtros: só poderia ser isso: nome do campo, tipo de comparação (igual, intervalo, etc), e dois valores porque pode precisar de um ou dois (em intervalo precisa de 2 valores)

Exemplo: codigo de cliente de 1 a 10

o Filtro vai ter
"CODIGO", 8, 1, 10
8 = FILTRO_RANGE = filtro por intervalo

Então, para todo e qualquer filtro, basta uma lista igual a essa: campo, tipo de filtro, intervalode, intervaloate

A lista pode ter elementos infinitos: codigo 1 a 10, nome "A" a "B", etc.

Relativamente simples.

E a origem pra criar esse filtro, é a outra lista que contém os campos, e qual o valor zerado/default de cada um.

primeira lista: codigo, nome, endereco, provavelmente com os default 0, Space(30) e Space(30)

segunda lista: conforme for selecionando um desses, vai aumentando

CODIGO, INTERVALO, 1, 10
NOME, CONTENDO, "JOSE", ""
NOME, CONTENDO, "QUINTAS", ""

e por aí vai.
Relativamente simples, mas em array.

É um achoice/tbrowse com os filtros já criados

É um achoice/tbrowse com a lista de campos - esse é o primeiro elemento de um filtro

É um achoice/tbrowse com a lista de tipos de filtro - esse é o segundo elemento do filtro

É o get de um ou dois valores, que serão usados para comparação de igual, maior, menor, intervalo, etc.
esses são os outros dois elementos do filtro, que começam com valores zerados.

Pensando em uma coisa de cada vez, fica mais simples.
A complicação é em trabalhar com esses arrays, e principalmente passando parâmetros.
Usando achoice(), acabei precisando de variável PRIVATE pra facilitar.

Poderíamos amadurecer essa idéia de filtros universais....
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

os elementos do array dos campos

Código: Selecionar todos

#define FIELD_NAME       1
#define FIELD_SELECTED   2
#define FIELD_EMPTYVALUE 3
os elementos do array de filtros

Código: Selecionar todos

#define FILTER_FIELD     1
#define FILTER_COMPARE   2
#define FILTER_RANGEFROM 3
#define FILTER_RANGETO   4
os tipos de comparação que coloquei

Código: Selecionar todos

#define COMPARE_NO_FILTER          1 //
#define COMPARE_EQUAL              2 // =
#define COMPARE_GREATHER_OR_EQUAL  3 // >=
#define COMPARE_LESS_OR_EQUAL      4 // <=
#define COMPARE_GREATHER           5 // >
#define COMPARE_LESS               6 // <
#define COMPARE_NOT_EQUAL          7 // !=
#define COMPARE_RANGE              8 // >= rangefrom .AND. <= rangeto
#define COMPARE_HAS_TEXT           9 // text $ field
#define COMPARE_NOT_HAS_TEXT      10 // ! text $ field
#define COMPARE_BEGIN_WITH_TEXT   11 // field = text*
#define COMPARE_IN_TEXT           12 // field $ text
#define COMPARE_NOT_IN_TEXT       13 // ! field $ text
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Aproveitando:

A montagem do filtro depois pode ser pra DBF ou MySQL do mesmo jeito, criando uma string.

Código: Selecionar todos

cFiltroSQL := "CODIGO >= 1 AND CODIGO <= 10"
cFiltroSQL += " AND NOME LIKE '%JOSE%'"

cFiltroDBF := "CODIGO >= 1 AND CODIGO <= 10"
cFiltroDBF += " AND 'JOSE' $ NOME"

conexao:Execute( "SELECT * FROM CLIENTES WHERE " + cFIltroSQL )

SET FILTER TO &( cFiltroDBF )
Detalhe importante no filtro em DBF:
Como está usando campo/conteúdo, NÃO DEPENTE DE VARIÁVEIS.
Esse é um problema comum que temos ao usar variáveis local/private/etc. que complica tudo, mas assim não tem problema.

Pois é... ao usar SQL... vemos certas coisas que fazíamos em DBF que eram problema.

Eu já disse por aqui:
A gente pode tirar idéia de onde menos se espera.
Isso de montar o comando SQL, dá uma idéia de fazer o mesmo com DBF, pra não ficar dependente de nada, ou até com o próprio SQL.

No final de tudo, seja qual for a seleção, o filtro é uma simples string.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

MediaMonkey / Aplicativos

Mensagem por JoséQuintas »

Mesmo assim, em DBF criei uma opção adicional:

Código: Selecionar todos

METHOD Filter() Class FilterClass

   LOCAL oElement, lReturn := .T., xValue

   FOR EACH oElement IN ::aFilterList
      xValue := FieldGet( FieldPos( oElement[ FIELD_NAME ] ) )
      DO CASE
      CASE oElement[ FILTER_COMPARE ] == COMPARE_NO_FILTER
      CASE oElement[ FILTER_COMPARE ] == COMPARE_EQUAL ;             lReturn := ( xValue == oElement[ FILTER_RANGEFROM ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_GREATHER_OR_EQUAL ; lReturn := ( xValue >= oElement[ FILTER_RANGEFROM ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_LESS_OR_EQUAL ;     lReturn := ( xValue <= oElement[ FILTER_RANGEFROM ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_GREATHER ;          lReturn := ( xValue >  oElement[ FILTER_RANGEFROM ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_LESS ;              lReturn := ( xValue <  oElement[ FILTER_RANGEFROM ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_NOT_EQUAL ;         lReturn := ( xValue != oElement[ FILTER_RANGEFROM ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_RANGE ;             lReturn := ( xValue >= oElement[ FILTER_RANGEFROM ] .AND. xValue <= oElement[ FILTER_RANGETO ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_HAS_TEXT ;          lReturn := ( Trim( oElement[ FILTER_RANGEFROM ] ) $ xValue )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_NOT_HAS_TEXT ;      lReturn := ( ! Trim( oElement[ FILTER_RANGEFROM ] ) $ xValue )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_BEGIN_WITH_TEXT ;   lReturn := ( Substr( xValue, 1, Len( Trim( oElement[ FILTER_RANGEFROM ] ) ) ) == Trim( oElement[ FILTER_RANGEFROM ] ) )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_IN_TEXT;            lReturn := ( xValue $ oElement[ FILTER_RANGEFROM ] )
      CASE oElement[ FILTER_COMPARE ] == COMPARE_NOT_IN_TEXT;        lReturn := ( ! xValue $ oElement[ FILTER_RANGEFROM ] )
      ENDCASE
      IF ! lReturn
         EXIT
      ENDIF
   NEXT

   RETURN lReturn
Opção 1:

Código: Selecionar todos

SET FILTER TO oFiltro:Filter()
Opção 2:

Código: Selecionar todos

DO WHILE ! Eof()
   Inkey()
   IF ! oFiltro:Filter()
      SKIP
      LOOP
   ENDIF
   SKIP
ENDDO
A segunda opção é interessante, pra quando o usuário clicar não aparecer "programa não está respondendo"

Parece complicado mas não é, é só lembrar do array:
campo, tipo de comparação, de/até

Código: Selecionar todos

   FOR EACH oElement IN ::aFilterList
      xValue := FieldGet( FieldPos( oElement[ FIELD_NAME ] ) )
Vai percorrer a lista de filtros, pegando o campo referência
Se por acaso o tipo de filtro é um intervalo

Código: Selecionar todos

      CASE oElement[ FILTER_COMPARE ] == COMPARE_RANGE
o que fazemos num intervalo? testamos o intervalo

Código: Selecionar todos

lReturn := ( xValue >= oElement[ FILTER_RANGEFROM ] .AND. xValue <= oElement[ FILTER_RANGETO ] )
As duas "variáveis", os elementos 3 e 4, que pra facilitar usei o #define.
Poderia ser FILTRO_INTERVALO, FILTRO_DE, FILTRO_ATE, é que pra deixar disponível, deixei em inglês.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder